Author: wtam Date: Wed Aug 5 23:11:04 2009 New Revision: 801457 URL: http://svn.apache.org/viewvc?rev=801457&view=rev Log: [CAMEL-1737] support Http centric client API in camel-cxfrs producer
Added: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsHeaderFilterStrategy.java (with props) camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest.java (with props) camel/trunk/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest-context.xml (with props) Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfComponent.java camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsBinding.java camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsComponent.java camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumer.java camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsInvoker.java camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsRouterTest.java Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfComponent.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfComponent.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfComponent.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfComponent.java Wed Aug 5 23:11:04 2009 @@ -61,7 +61,6 @@ CxfEndpointBean.class); result = new CxfSpringEndpoint(this, bean); - setEndpointHeaderFilterStrategy(result); // Apply Spring bean properties (including # notation referenced bean). Note that the // Spring bean properties values can be overridden by property defined in URI query. @@ -78,6 +77,7 @@ result = new CxfEndpoint(remaining, this); } + setEndpointHeaderFilterStrategy(result); return result; } Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java Wed Aug 5 23:11:04 2009 @@ -45,7 +45,6 @@ String CAMEL_CXF_RS_USING_HTTP_API = "CamelCxfRsUsingHttpAPI"; String CAMEL_CXF_RS_VAR_VALUES = "CamelCxfRsVarValues"; String CAMEL_CXF_RS_RESPONSE_CLASS = "CamelCxfRsResponseClass"; - String CAMEL_CXF_RS_METHOD = "CamelCxfRsMethod"; String CAMEL_CXF_RS_OPERATION_RESOURCE_INFO_STACK = "CamelCxfRsOperationResourceInfoStack"; } Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java Wed Aug 5 23:11:04 2009 @@ -17,10 +17,12 @@ package org.apache.camel.component.cxf.converter; import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import javax.ws.rs.core.Response; import javax.xml.soap.SOAPMessage; import org.apache.camel.Converter; @@ -119,6 +121,30 @@ public static DataFormat toDataFormat(final String name) { return DataFormat.valueOf(name.toUpperCase()); } + + @Converter + public static InputStream toInputStream(Response response, Exchange exchange) { + + Object obj = response.getEntity(); + + if (obj == null) { + return null; + } + + if (obj instanceof InputStream) { + // short circuit the lookup + return (InputStream)obj; + } + + TypeConverterRegistry registry = exchange.getContext().getTypeConverterRegistry(); + TypeConverter tc = registry.lookup(InputStream.class, obj.getClass()); + + if (tc != null) { + return tc.convertTo(InputStream.class, exchange, obj); + } + + return null; + } /** * Use a fallback type converter so we can convert the embedded list element Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsBinding.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsBinding.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsBinding.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsBinding.java Wed Aug 5 23:11:04 2009 @@ -20,8 +20,14 @@ import java.lang.reflect.Method; import java.util.Map; +import javax.ws.rs.core.MultivaluedMap; import org.apache.cxf.message.Exchange; +/** + * Interface to bind between Camel and CXF exchange for RESTful resources. + * + * @version $Revision$ + */ public interface CxfRsBinding { /** @@ -47,5 +53,53 @@ */ Object populateCxfRsResponseFromExchange(org.apache.camel.Exchange camelExchange, Exchange cxfExchange) throws Exception; + + /** + * Bind the camel in message body to a request body that gets passed + * to CXF RS {...@link org.apache.cxf.jaxrs.client.WebClient} APIs. + * + * @param camelMessage the source message + * @param camelExchange the Camel exchange + * @return the request object to be passed to invoke a WebClient + * @throws Exception + */ + Object bindCamelMessageBodyToRequestBody(org.apache.camel.Message camelMessage, + org.apache.camel.Exchange camelExchange) + throws Exception; + + /** + * Bind the camel headers to request headers that gets passed to CXF RS + * {...@link org.apache.cxf.jaxrs.client.WebClient} APIs. + * + * @param camelHeaders the source headers + * @param camelExchange the Camel exchange + * @param headers to be passed to WebClient + * @throws Exception + */ + MultivaluedMap<String, String> bindCamelHeadersToRequestHeaders(Map<String, Object> camelHeaders, + org.apache.camel.Exchange camelExchange) + throws Exception; + + + /** + * Bind the HTTP response body to camel out body + * @param response + * @param exchange + * @return the object to be set in the Camel out message body + */ + Object bindResponseToCamelBody(Object response, org.apache.camel.Exchange camelExchange) + throws Exception; + + /** + * Bind the response headers to camel out headers. + * + * @param response + * @param exchange + * @return headers to be set in the Camel out message + * @throws Exception + */ + Map<String, Object> bindResponseHeadersToCamelHeaders(Object response, + org.apache.camel.Exchange exchange) + throws Exception; } Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsComponent.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsComponent.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsComponent.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsComponent.java Wed Aug 5 23:11:04 2009 @@ -23,9 +23,6 @@ import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; import org.apache.camel.component.cxf.CxfConstants; -import org.apache.camel.component.cxf.CxfEndpoint; -import org.apache.camel.component.cxf.CxfSpringEndpoint; -import org.apache.camel.component.cxf.spring.CxfEndpointBean; import org.apache.camel.impl.HeaderFilterStrategyComponent; import org.apache.camel.util.CamelContextHelper; import org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean; @@ -42,6 +39,7 @@ super(context); } + @SuppressWarnings("unchecked") @Override protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { CxfRsEndpoint answer = null; @@ -56,7 +54,6 @@ AbstractJAXRSFactoryBean.class); answer = new CxfRsSpringEndpoint(this.getCamelContext(), bean); - setEndpointHeaderFilterStrategy(answer); // Apply Spring bean properties (including # notation referenced bean). Note that the // Spring bean properties values can be overridden by property defined in URI query. @@ -73,6 +70,7 @@ answer = new CxfRsEndpoint(remaining, this); } + setEndpointHeaderFilterStrategy(answer); return answer; } Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumer.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumer.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumer.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumer.java Wed Aug 5 23:11:04 2009 @@ -17,13 +17,9 @@ package org.apache.camel.component.cxf.jaxrs; -import org.apache.camel.Endpoint; import org.apache.camel.Processor; import org.apache.camel.impl.DefaultConsumer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.cxf.endpoint.Server; -import org.apache.cxf.frontend.ServerFactoryBean; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; /** @@ -33,7 +29,6 @@ * It is also responsible for converting and sending back responses to CXF client. */ public class CxfRsConsumer extends DefaultConsumer { - private static final Log LOG = LogFactory.getLog(CxfRsConsumer.class); private Server server; public CxfRsConsumer(CxfRsEndpoint endpoint, Processor processor) { Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java Wed Aug 5 23:11:04 2009 @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.camel.CamelContext; import org.apache.camel.Component; @@ -30,6 +31,9 @@ import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.spi.HeaderFilterStrategyAware; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean; @@ -37,9 +41,13 @@ * */ public class CxfRsEndpoint extends DefaultEndpoint implements HeaderFilterStrategyAware { - private List<Class> resourceClasses; + private static final Log LOG = LogFactory.getLog(CxfRsEndpoint.class); + + private List<Class<?>> resourceClasses; private HeaderFilterStrategy headerFilterStrategy; private CxfRsBinding binding; + + private AtomicBoolean bindingInitialized = new AtomicBoolean(false); public CxfRsEndpoint(String endpointUri, CamelContext camelContext) { super(endpointUri, camelContext); @@ -49,12 +57,22 @@ super(endpointUri, component); } - public HeaderFilterStrategy getHeaderFilterStrategy() { + public HeaderFilterStrategy getHeaderFilterStrategy() { + if (headerFilterStrategy == null) { + headerFilterStrategy = new CxfRsHeaderFilterStrategy(); + if (LOG.isDebugEnabled()) { + LOG.debug("Create default header filter strategy " + headerFilterStrategy); + } + } return headerFilterStrategy; } public void setHeaderFilterStrategy(HeaderFilterStrategy strategy) { headerFilterStrategy = strategy; + if (binding instanceof HeaderFilterStrategyAware) { + ((HeaderFilterStrategyAware)binding) + .setHeaderFilterStrategy(headerFilterStrategy); + } } public Consumer createConsumer(Processor processor) throws Exception { @@ -71,19 +89,29 @@ public void setBinding(CxfRsBinding binding) { this.binding = binding; + bindingInitialized.set(false); + } public CxfRsBinding getBinding() { if (binding == null) { binding = new DefaultCxfRsBinding(); + if (LOG.isDebugEnabled()) { + LOG.debug("Create default CXF Binding " + binding); + } } + + if (!bindingInitialized.getAndSet(true) && binding instanceof HeaderFilterStrategyAware) { + ((HeaderFilterStrategyAware)binding).setHeaderFilterStrategy(getHeaderFilterStrategy()); + } + return binding; } protected void setupJAXRSServerFactoryBean(JAXRSServerFactoryBean sfb) { // address sfb.setAddress(getEndpointUri()); - sfb.setResourceClasses(getResourceClasses()); + sfb.setResourceClasses(CastUtils.cast(getResourceClasses(), Class.class)); sfb.setStart(false); } @@ -107,15 +135,15 @@ return answer; } - public List<Class> getResourceClasses() { + public List<Class<?>> getResourceClasses() { return resourceClasses; } - public void setResourceClasses(List<Class> classes) { + public void setResourceClasses(List<Class<?>> classes) { resourceClasses = classes; } - public void setResourceClasses(Class... classes) { + public void setResourceClasses(Class<?>... classes) { setResourceClasses(Arrays.asList(classes)); } Added: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsHeaderFilterStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsHeaderFilterStrategy.java?rev=801457&view=auto ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsHeaderFilterStrategy.java (added) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsHeaderFilterStrategy.java Wed Aug 5 23:11:04 2009 @@ -0,0 +1,42 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.component.cxf.jaxrs; + +import org.apache.camel.Exchange; +import org.apache.camel.component.cxf.CxfConstants; +import org.apache.camel.impl.DefaultHeaderFilterStrategy; + +/** + * + * @version $Revision$ + */ +public class CxfRsHeaderFilterStrategy extends DefaultHeaderFilterStrategy { + public CxfRsHeaderFilterStrategy() { + initialize(); + } + + protected void initialize() { + getOutFilter().add(CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS); + getOutFilter().add(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API); + getOutFilter().add(CxfConstants.CAMEL_CXF_RS_OPERATION_RESOURCE_INFO_STACK); + getOutFilter().add(CxfConstants.CAMEL_CXF_RS_VAR_VALUES); + getOutFilter().add(CxfConstants.OPERATION_NAME); + getOutFilter().add(Exchange.HTTP_METHOD); + getOutFilter().add(Exchange.HTTP_PATH); + } + +} Propchange: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsHeaderFilterStrategy.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsHeaderFilterStrategy.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsInvoker.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsInvoker.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsInvoker.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsInvoker.java Wed Aug 5 23:11:04 2009 @@ -17,8 +17,6 @@ package org.apache.camel.component.cxf.jaxrs; import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.logging.Level; import javax.ws.rs.WebApplicationException; Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java Wed Aug 5 23:11:04 2009 @@ -17,7 +17,6 @@ package org.apache.camel.component.cxf.jaxrs; -import java.io.InputStream; import java.lang.reflect.Method; import java.util.List; @@ -27,11 +26,12 @@ import org.apache.camel.Message; import org.apache.camel.component.cxf.CxfConstants; import org.apache.camel.impl.DefaultProducer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean; import org.apache.cxf.jaxrs.client.Client; import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean; import org.apache.cxf.jaxrs.client.WebClient; -import org.apache.cxf.message.MessageContentsList; /** * CxfRsProducer binds a Camel exchange to a CXF exchange, acts as a CXF @@ -39,6 +39,9 @@ * according to resource annotation. Any response will be bound to Camel exchange. */ public class CxfRsProducer extends DefaultProducer { + + private static final Log LOG = LogFactory.getLog(CxfRsProducer.class); + JAXRSClientFactoryBean cfb; public CxfRsProducer(CxfRsEndpoint endpoint) { @@ -47,6 +50,11 @@ } public void process(Exchange exchange) throws Exception { + + if (LOG.isTraceEnabled()) { + LOG.trace("Process exchange: " + exchange); + } + Message inMessage = exchange.getIn(); Boolean httpClientAPI = inMessage.getHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.class); if (httpClientAPI != null && httpClientAPI.booleanValue()) { @@ -58,37 +66,57 @@ } @SuppressWarnings("unchecked") - protected void invokeHttpClient(Exchange exchange) { + protected void invokeHttpClient(Exchange exchange) throws Exception { Message inMessage = exchange.getIn(); WebClient client = cfb.createWebClient(); + String httpMethod = inMessage.getHeader(Exchange.HTTP_METHOD, String.class); Class responseClass = inMessage.getHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS, Class.class); String path = inMessage.getHeader(Exchange.HTTP_PATH, String.class); + if (LOG.isTraceEnabled()) { + LOG.trace("HTTP method = " + httpMethod); + LOG.trace("path = " + path); + LOG.trace("responseClass = " + responseClass); + } + + // set the path if (path != null) { client.path(path); } + + CxfRsBinding binding = ((CxfRsEndpoint)getEndpoint()).getBinding(); + + // set the body Object body = null; if (!"GET".equals(httpMethod)) { - // need to check the request object - body = checkRequestObject(inMessage.getBody()); + // need to check the request object. + body = binding.bindCamelMessageBodyToRequestBody(inMessage, exchange); + if (LOG.isTraceEnabled()) { + LOG.trace("Request body = " + body); + } } - /*String acceptContentType = inMessage.getHeader(Exchange.ACCEPT_CONTENT_TYPE, String.class); - if (acceptContentType != null) { - client.accept(acceptContentType); - }*/ + // set headers + client.headers(binding.bindCamelHeadersToRequestHeaders(inMessage.getHeaders(), + exchange)); + + // invoke the client Object response = null; - if (responseClass == null) { - response = client.invoke(httpMethod, body, InputStream.class); - } else if (responseClass.equals(Response.class)) { + if (responseClass == null || Response.class.equals(responseClass)) { response = client.invoke(httpMethod, body); } else { response = client.invoke(httpMethod, body, responseClass); } - - if (exchange.getPattern().isOutCapable()) { - exchange.getOut().setBody(response); + + // set response + if (exchange.getPattern().isOutCapable()) { + if (LOG.isTraceEnabled()) { + LOG.trace("Response body = " + response); + } + + exchange.getOut().setBody(binding.bindResponseToCamelBody(response, exchange)); + exchange.getOut().setHeaders(binding.bindResponseHeadersToCamelHeaders(response, exchange)); } } @@ -116,9 +144,10 @@ } } + @SuppressWarnings("unchecked") private Method findRightMethod(List<Class> resourceClasses, String methodName, Class[] parameterTypes) throws NoSuchMethodException { Method answer = null; - for (Class clazz : resourceClasses) { + for (Class<?> clazz : resourceClasses) { try { answer = clazz.getMethod(methodName, parameterTypes); } catch (NoSuchMethodException ex) { @@ -134,21 +163,9 @@ + "withe these parameter " + arrayToString(parameterTypes)); } - private Object checkRequestObject(Object request) { - if (request != null) { - if (request instanceof MessageContentsList) { - request = ((MessageContentsList)request).get(0); - } else if (request instanceof List) { - request = ((List)request).get(0); - } else if (request.getClass().isArray()) { - request = ((Object[])request)[0]; - } - } - return request; - } - private Class[] getParameterTypes(Object[] objects) { - Class[] answer = new Class[objects.length]; + private Class<?>[] getParameterTypes(Object[] objects) { + Class<?>[] answer = new Class[objects.length]; int i = 0; for (Object obj : objects) { answer[i] = obj.getClass(); Modified: camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java (original) +++ camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java Wed Aug 5 23:11:04 2009 @@ -18,27 +18,58 @@ package org.apache.camel.component.cxf.jaxrs; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.component.cxf.CxfConstants; import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.spi.HeaderFilterStrategyAware; -import org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor; -import org.apache.cxf.jaxrs.model.MethodInvocationInfo; -import org.apache.cxf.jaxrs.model.OperationResourceInfo; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.cxf.jaxrs.impl.MetadataMap; import org.apache.cxf.jaxrs.model.OperationResourceInfoStack; -import org.apache.cxf.jaxrs.model.URITemplate; +import org.apache.cxf.message.MessageContentsList; +/** + * Default strategy to bind between Camel and CXF exchange for RESTful resources. + * + * + * @version $Revision$ + */ public class DefaultCxfRsBinding implements CxfRsBinding, HeaderFilterStrategyAware { + private static final Log LOG = LogFactory.getLog(DefaultCxfRsBinding.class); + + protected Map<String, String> camelToCxfHeaderMap = new HashMap<String, String>(); + protected Map<String, String> cxfToCamelHeaderMap = new HashMap<String, String>(); + private HeaderFilterStrategy headerFilterStrategy; + public DefaultCxfRsBinding() { + // initialize mappings between Camel and CXF header names + + camelToCxfHeaderMap.put(Exchange.HTTP_URI, org.apache.cxf.message.Message.REQUEST_URI); + camelToCxfHeaderMap.put(Exchange.HTTP_METHOD, org.apache.cxf.message.Message.HTTP_REQUEST_METHOD); + camelToCxfHeaderMap.put(Exchange.HTTP_PATH, org.apache.cxf.message.Message.PATH_INFO); + camelToCxfHeaderMap.put(Exchange.CONTENT_TYPE, org.apache.cxf.message.Message.CONTENT_TYPE); + camelToCxfHeaderMap.put(Exchange.HTTP_CHARACTER_ENCODING, org.apache.cxf.message.Message.ENCODING); + camelToCxfHeaderMap.put(Exchange.HTTP_QUERY, org.apache.cxf.message.Message.QUERY_STRING); + camelToCxfHeaderMap.put(Exchange.ACCEPT_CONTENT_TYPE, org.apache.cxf.message.Message.ACCEPT_CONTENT_TYPE); + + cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.REQUEST_URI, Exchange.HTTP_URI); + cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.HTTP_REQUEST_METHOD, Exchange.HTTP_METHOD); + cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.PATH_INFO, Exchange.HTTP_PATH); + cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.CONTENT_TYPE, Exchange.CONTENT_TYPE); + cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.ENCODING, Exchange.HTTP_CHARACTER_ENCODING); + cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.QUERY_STRING, Exchange.HTTP_QUERY); + cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.ACCEPT_CONTENT_TYPE, Exchange.ACCEPT_CONTENT_TYPE); + } + public Object populateCxfRsResponseFromExchange(Exchange camelExchange, org.apache.cxf.message.Exchange cxfExchange) throws Exception { if (camelExchange.isFailed()) { @@ -55,6 +86,8 @@ //Copy the CXF message header into the Camel inMessage org.apache.cxf.message.Message cxfMessage = cxfExchange.getInMessage(); + // TODO use header filter strategy and cxfToCamelHeaderMap + copyMessageHeader(cxfMessage, camelMessage, org.apache.cxf.message.Message.REQUEST_URI, Exchange.HTTP_URI); copyMessageHeader(cxfMessage, camelMessage, org.apache.cxf.message.Message.HTTP_REQUEST_METHOD, Exchange.HTTP_METHOD); @@ -75,11 +108,111 @@ camelMessage.setHeader(CxfConstants.OPERATION_NAME, method.getName()); - camelMessage.setHeader(CxfConstants.CAMEL_CXF_RS_METHOD, method); - camelMessage.setBody(paramArray); } + + public MultivaluedMap<String, String> bindCamelHeadersToRequestHeaders(Map<String, Object> camelHeaders, + Exchange camelExchange) + throws Exception { + + MultivaluedMap<String, String> answer = new MetadataMap<String, String>(); + for (Map.Entry<String, Object> entry : camelHeaders.entrySet()) { + + if (headerFilterStrategy.applyFilterToCamelHeaders(entry.getKey(), entry.getValue(), camelExchange)) { + if (LOG.isTraceEnabled()) { + LOG.trace("Drop Camel header: " + entry.getKey() + "=" + entry.getValue()); + } + continue; + } + + String mappedHeaderName = camelToCxfHeaderMap.get(entry.getKey()); + if (mappedHeaderName == null) { + mappedHeaderName = entry.getKey(); + } + + if (LOG.isTraceEnabled()) { + LOG.trace("Propagate Camel header: " + entry.getKey() + "=" + entry.getValue() + " as " + + mappedHeaderName); + } + + answer.putSingle(mappedHeaderName, entry.getValue().toString()); + } + return answer; + } + + /** + * This method call Message.getBody({...@link MessageContentsList}) to allow + * an appropriate converter to kick in even through we only read the first + * element off the MessageContextList. If that returns null, we check + * the body to see if it is a List or an array and then return the first + * element. If that fails, we will simply return the object. + */ + public Object bindCamelMessageBodyToRequestBody(Message camelMessage, Exchange camelExchange) + throws Exception { + + Object request = camelMessage.getBody(MessageContentsList.class); + if (request != null) { + return ((MessageContentsList)request).get(0); + } + + request = camelMessage.getBody(); + if (request instanceof List) { + request = ((List<?>)request).get(0); + } else if (request.getClass().isArray()) { + request = ((Object[])request)[0]; + } + + return request; + + } + + /** + * We will return an empty Map unless the response parameter is a {...@link Response} object. + */ + public Map<String, Object> bindResponseHeadersToCamelHeaders(Object response, Exchange exchange) + throws Exception { + + Map<String, Object> answer = new HashMap<String, Object>(); + if (response instanceof Response) { + + for (Map.Entry<String, List<Object>> entry : ((Response)response).getMetadata().entrySet()) { + if (!headerFilterStrategy.applyFilterToExternalHeaders(entry.getKey(), + entry.getValue(), exchange)) { + + String mappedHeaderName = cxfToCamelHeaderMap.get(entry.getKey()); + if (mappedHeaderName == null) { + mappedHeaderName = entry.getKey(); + } + + if (LOG.isTraceEnabled()) { + LOG.trace("Populate external header " + entry.getKey() + "=" + entry.getValue() + + " as " + mappedHeaderName); + } + + answer.put(mappedHeaderName, entry.getValue().get(0)); + + } else { + if (LOG.isTraceEnabled()) { + LOG.trace("Drop external header " + entry.getKey() + "=" + entry.getValue()); + } + } + } + + // put response code in Camel message header + answer.put(Exchange.HTTP_RESPONSE_CODE, ((Response)response).getStatus()); + } + + return answer; + } + + /** + * By default, we just return the response object. + */ + public Object bindResponseToCamelBody(Object response, Exchange camelExchange) throws Exception { + return response; + } + public HeaderFilterStrategy getHeaderFilterStrategy() { return headerFilterStrategy; } @@ -89,6 +222,22 @@ headerFilterStrategy = strategy; } + public Map<String, String> getCamelToCxfHeaderMap() { + return camelToCxfHeaderMap; + } + + public void setCamelToCxfHeaderMap(Map<String, String> camelToCxfHeaderMap) { + this.camelToCxfHeaderMap = camelToCxfHeaderMap; + } + + public Map<String, String> getCxfToCamelHeaderMap() { + return cxfToCamelHeaderMap; + } + + public void setCxfToCamelHeaderMap(Map<String, String> cxfToCamelHeaderMap) { + this.cxfToCamelHeaderMap = cxfToCamelHeaderMap; + } + protected void copyMessageHeader(org.apache.cxf.message.Message cxfMessage, Message camelMessage, String cxfKey, String camelKey) { if (cxfMessage.get(cxfKey) != null) { camelMessage.setHeader(camelKey, cxfMessage.get(cxfKey)); Modified: camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java (original) +++ camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java Wed Aug 5 23:11:04 2009 @@ -17,7 +17,6 @@ package org.apache.camel.component.cxf.jaxrs; import java.io.InputStream; -import java.net.MalformedURLException; import java.net.URL; import org.apache.camel.Exchange; Added: camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest.java?rev=801457&view=auto ============================================================================== --- camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest.java (added) +++ camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest.java Wed Aug 5 23:11:04 2009 @@ -0,0 +1,142 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.component.cxf.jaxrs; + +import java.io.InputStream; + +import javax.ws.rs.core.Response; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.ExchangePattern; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.component.cxf.CxfConstants; +import org.apache.camel.component.cxf.util.CxfUtils; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Unit test that verify header propagation functionality for CxfRsProducer + * that uses WebClient API. + * + * @version $Revision$ + */ +...@contextconfiguration +public class CxfRsProducerHeaderTest extends AbstractJUnit4SpringContextTests { + + private static final Object RESPONSE = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<Customer><id>123</id><name>John</name></Customer>"; + + @Autowired + protected CamelContext camelContext; + + @Test + public void testInvokeThatDoesNotInvolveHeaders() throws Exception { + Exchange exchange = camelContext.createProducerTemplate().send("direct://http", new Processor() { + + public void process(Exchange exchange) throws Exception { + exchange.setPattern(ExchangePattern.InOut); + Message inMessage = exchange.getIn(); + inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.TRUE); + inMessage.setHeader(Exchange.HTTP_METHOD, "GET"); + inMessage.setHeader(Exchange.HTTP_PATH, "/customerservice/customers/123"); + inMessage.setBody(null); + } + + }); + + // verify the out message is a Response object by default + Response response = (Response)exchange.getOut().getBody(); + assertNotNull("The response should not be null ", response); + assertEquals(200, response.getStatus()); + + // test converter (from Response to InputStream) + assertEquals(RESPONSE, CxfUtils.getStringFromInputStream(exchange.getOut().getBody(InputStream.class))); + } + + @Test + public void testHeaderFilteringAndPropagation() throws Exception { + Exchange exchange = camelContext.createProducerTemplate().send("direct://http2", new Processor() { + + public void process(Exchange exchange) throws Exception { + exchange.setPattern(ExchangePattern.InOut); + Message inMessage = exchange.getIn(); + inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.TRUE); + inMessage.setHeader(Exchange.HTTP_METHOD, "GET"); + inMessage.setHeader(Exchange.HTTP_PATH, "/customerservice/customers/123"); + inMessage.setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json"); + inMessage.setHeader("my-user-defined-header", "my-value"); + inMessage.setBody(null); + } + + }); + + // get the response message + Response response = (Response)exchange.getOut().getBody(); + + // check the response code on the Response object as set by the "HttpProcess" + assertEquals(200, response.getStatus()); + + // get out message + Message outMessage = exchange.getOut(); + + // verify the content-type header sent by the "HttpProcess" + assertEquals("text/xml", outMessage.getHeader(Exchange.CONTENT_TYPE)); + + // check the user defined header echoed by the "HttpProcess" + assertEquals("my-value", outMessage.getHeader("echo-my-user-defined-header")); + + // check the Accept header echoed by the "HttpProcess" + assertEquals("application/json", outMessage.getHeader("echo-accept")); + + // make sure the HttpProcess have not seen CxfConstants.CAMEL_CXF_RS_USING_HTTP_API + assertNull(outMessage.getHeader("failed-header-using-http-api")); + + // make sure response code has been set in out header + assertEquals(200, outMessage.getHeader(Exchange.HTTP_RESPONSE_CODE)); + + } + + public static class HttpProcessor implements Processor { + + public void process(Exchange exchange) throws Exception { + Message in = exchange.getIn(); + Message out = exchange.getOut(); + + if (in.getHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API) != null) { + // this should have been filtered + out.setHeader("failed-header-using-http-api", CxfConstants.CAMEL_CXF_RS_USING_HTTP_API); + } + + out.setHeader("echo-accept", in.getHeader("Accept")); + out.setHeader("echo-my-user-defined-header", in.getHeader("my-user-defined-header")); + + exchange.getOut().setHeader(Exchange.HTTP_RESPONSE_CODE, 200); + exchange.getOut().setHeader(Exchange.CONTENT_TYPE, "text/xml"); + + + } + + } +} Propchange: camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Modified: camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsRouterTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsRouterTest.java?rev=801457&r1=801456&r2=801457&view=diff ============================================================================== --- camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsRouterTest.java (original) +++ camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsRouterTest.java Wed Aug 5 23:11:04 2009 @@ -17,12 +17,9 @@ package org.apache.camel.component.cxf.jaxrs; -import java.io.InputStream; -import java.net.URL; - -import org.apache.camel.component.cxf.util.CxfUtils; import org.apache.camel.test.junit4.CamelSpringTestSupport; import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PutMethod; import org.apache.commons.httpclient.methods.RequestEntity; @@ -31,8 +28,6 @@ import org.springframework.context.support.AbstractXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; -import static org.junit.Assert.assertEquals; - public class CxfRsRouterTest extends CamelSpringTestSupport { private static final String PUT_REQUEST = "<Customer><name>Mary</name><id>123</id></Customer>"; private static final String POST_REQUEST = "<Customer><name>Jack</name></Customer>"; @@ -43,18 +38,35 @@ } @Test - public void testGetCustomer() throws Exception { - URL url = new URL("http://localhost:9000/customerservice/customers/123"); + public void testGetCustomer() throws Exception { + GetMethod get = new GetMethod("http://localhost:9000/customerservice/customers/123"); + get.addRequestHeader("Accept" , "application/json"); + + HttpClient httpclient = new HttpClient(); - InputStream in = url.openStream(); - assertEquals("{\"Customer\":{\"id\":123,\"name\":\"John\"}}", CxfUtils.getStringFromInputStream(in)); + try { + assertEquals(200, httpclient.executeMethod(get)); + assertEquals("{\"Customer\":{\"id\":123,\"name\":\"John\"}}", + get.getResponseBodyAsString()); + } finally { + get.releaseConnection(); + } } @Test public void testGetSubResource() throws Exception { - URL url = new URL("http://localhost:9000/customerservice/orders/223/products/323"); - InputStream in = url.openStream(); - assertEquals("{\"Product\":{\"description\":\"product 323\",\"id\":323}}", CxfUtils.getStringFromInputStream(in)); + GetMethod get = new GetMethod("http://localhost:9000/customerservice/orders/223/products/323"); + get.addRequestHeader("Accept" , "application/json"); + + HttpClient httpclient = new HttpClient(); + + try { + assertEquals(200, httpclient.executeMethod(get)); + assertEquals("{\"Product\":{\"description\":\"product 323\",\"id\":323}}", + get.getResponseBodyAsString()); + } finally { + get.releaseConnection(); + } } @Test Added: camel/trunk/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest-context.xml URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest-context.xml?rev=801457&view=auto ============================================================================== --- camel/trunk/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest-context.xml (added) +++ camel/trunk/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest-context.xml Wed Aug 5 23:11:04 2009 @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:cxf="http://camel.apache.org/schema/cxf" + xmlns:jaxrs="http://cxf.apache.org/jaxrs" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd + http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + "> + + <jaxrs:server id="restService" + address="http://localhost:9002" + staticSubresourceResolution="true"> + <jaxrs:serviceBeans> + <ref bean="customerService"/> + </jaxrs:serviceBeans> + </jaxrs:server> + + <bean id="customerService" class="org.apache.camel.component.cxf.jaxrs.testbean.CustomerService" /> + + <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct://http"/> + <to uri="cxfrs://http://localhost:9002"/> + </route> + + <route> + <from uri="direct://http2"/> + <to uri="cxfrs://http://localhost:9003"/> + </route> + + <route> + <from uri="jetty://http://localhost:9003?matchOnUriPrefix=true"/> + <process ref="httpProcessor" /> + </route> + </camelContext> + + <bean id="httpProcessor" class="org.apache.camel.component.cxf.jaxrs.CxfRsProducerHeaderTest$HttpProcessor" /> +</beans> Propchange: camel/trunk/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest-context.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: camel/trunk/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest-context.xml ------------------------------------------------------------------------------ svn:keywords = Rev Date Propchange: camel/trunk/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsProducerHeaderTest-context.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml