You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2011/01/03 16:17:57 UTC
svn commit: r1054645 - in /cxf/trunk:
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/
systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/
systests/jaxrs/src/test/java/o...
Author: sergeyb
Date: Mon Jan 3 15:17:54 2011
New Revision: 1054645
URL: http://svn.apache.org/viewvc?rev=1054645&view=rev
Log:
[CXF-3227] Adding JAXRSDataBinding
Added:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXRSDataBinding.java (with props)
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorld.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorldImpl.java
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_soap_rest/WEB-INF/beans.xml
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java?rev=1054645&r1=1054644&r2=1054645&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java Mon Jan 3 15:17:54 2011
@@ -81,8 +81,6 @@ public class ThreadLocalMessageContext e
public void put(Object key, Object value) {
if (get() != null) {
get().put(key, value);
- } else {
- throw new IllegalStateException("MessageContext is not set");
}
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java?rev=1054645&r1=1054644&r2=1054645&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java Mon Jan 3 15:17:54 2011
@@ -77,6 +77,8 @@ import org.apache.cxf.jaxrs.utils.Inject
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
import org.apache.cxf.jaxrs.utils.ResourceUtils;
import org.apache.cxf.jaxrs.utils.schemas.SchemaHandler;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptorChain;
import org.apache.cxf.staxutils.DelegatingXMLStreamWriter;
import org.apache.cxf.staxutils.DepthXMLStreamReader;
import org.apache.cxf.staxutils.StaxStreamFilter;
@@ -171,15 +173,26 @@ public abstract class AbstractJAXBProvid
protected void checkContentLength() {
if (mc != null) {
- List<String> values = mc.getHttpHeaders().getRequestHeader(HttpHeaders.CONTENT_LENGTH);
- if (values.size() == 1 && "0".equals(values.get(0))) {
- String message = new org.apache.cxf.common.i18n.Message("EMPTY_BODY", BUNDLE).toString();
- LOG.warning(message);
- throw new WebApplicationException(400);
+ HttpHeaders headers = mc.getHttpHeaders();
+ if (headers != null) {
+ List<String> values = mc.getHttpHeaders().getRequestHeader(HttpHeaders.CONTENT_LENGTH);
+ if (values.size() == 1 && "0".equals(values.get(0))) {
+ String message = new org.apache.cxf.common.i18n.Message("EMPTY_BODY", BUNDLE).toString();
+ LOG.warning(message);
+ throw new WebApplicationException(400);
+ }
}
}
}
+ protected <T> T getStaxHandlerFromCurrentMessage(Class<T> staxCls) {
+ Message m = PhaseInterceptorChain.getCurrentMessage();
+ if (m != null) {
+ return staxCls.cast(m.getContent(staxCls));
+ }
+ return null;
+ }
+
@SuppressWarnings("unchecked")
protected Object convertToJaxbElementIfNeeded(Object obj, Class<?> cls, Type genericType)
throws Exception {
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java?rev=1054645&r1=1054644&r2=1054645&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java Mon Jan 3 15:17:54 2011
@@ -205,11 +205,15 @@ public class JAXBElementProvider extends
reader = factory.createXMLStreamReader(is);
} catch (XMLStreamException e) {
throw new WebApplicationException(
- new RuntimeException("Cant' create XMLStreamReader", e));
+ new RuntimeException("Can not create XMLStreamReader", e));
}
}
}
+ if (reader == null && is == null) {
+ reader = getStaxHandlerFromCurrentMessage(XMLStreamReader.class);
+ }
+
reader = createTransformReaderIfNeeded(reader, is);
if (InjectionUtils.isSupportedCollectionOrArray(type)) {
return new JAXBCollectionWrapperReader(createNewReaderIfNeeded(reader, is));
@@ -235,7 +239,7 @@ public class JAXBElementProvider extends
throws IOException {
try {
Object actualObject = checkAdapter(obj, cls, anns, true);
- Class<?> actualClass = obj != actualObject ? actualObject.getClass() : cls;
+ Class<?> actualClass = obj != actualObject || cls.isInterface() ? actualObject.getClass() : cls;
String encoding = HttpUtils.getSetEncoding(m, headers, null);
if (InjectionUtils.isSupportedCollectionOrArray(actualClass)) {
actualClass = InjectionUtils.getActualType(genericType);
@@ -385,12 +389,15 @@ public class JAXBElementProvider extends
}
XMLStreamWriter writer = getStreamWriter(obj, os, mt);
if (writer != null) {
- if (mc != null) {
+ if (os == null) {
+ ms.setProperty(Marshaller.JAXB_FRAGMENT, true);
+ } else if (mc != null) {
if (mc.getContent(XMLStreamWriter.class) != null) {
ms.setProperty(Marshaller.JAXB_FRAGMENT, true);
}
- mc.put(XMLStreamWriter.class.getName(), writer);
- }
+ mc.put(XMLStreamWriter.class.getName(), writer);
+ }
+
marshalToWriter(ms, obj, writer, mt);
if (mc != null && mc.getContent(XMLStreamWriter.class) != null) {
writer.writeEndDocument();
@@ -421,6 +428,10 @@ public class JAXBElementProvider extends
if (writer == null && enableStreaming) {
writer = StaxUtils.createXMLStreamWriter(os);
}
+ }
+
+ if (writer == null && os == null) {
+ writer = getStaxHandlerFromCurrentMessage(XMLStreamWriter.class);
}
return createTransformWriterIfNeeded(writer, os);
}
Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXRSDataBinding.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXRSDataBinding.java?rev=1054645&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXRSDataBinding.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXRSDataBinding.java Mon Jan 3 15:17:54 2011
@@ -0,0 +1,193 @@
+/**
+ * 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.cxf.jaxrs.provider;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.validation.Schema;
+
+import org.apache.cxf.databinding.AbstractDataBinding;
+import org.apache.cxf.databinding.DataReader;
+import org.apache.cxf.databinding.DataWriter;
+import org.apache.cxf.frontend.MethodDispatcher;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.message.Attachment;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.service.Service;
+import org.apache.cxf.service.model.BindingOperationInfo;
+import org.apache.cxf.service.model.MessagePartInfo;
+
+/**
+ * CXF DataBinding implementation wrapping JAX-RS providers
+ */
+public class JAXRSDataBinding extends AbstractDataBinding {
+
+ private static final Class<?> SUPPORTED_READER_FORMATS[] = new Class<?>[] {XMLStreamReader.class};
+ private static final Class<?> SUPPORTED_WRITER_FORMATS[] = new Class<?>[] {XMLStreamWriter.class};
+
+ private MessageBodyReader xmlReader;
+ private MessageBodyWriter xmlWriter;
+
+ public void setProvider(Object provider) {
+ if (!(provider instanceof MessageBodyWriter)) {
+ throw new IllegalArgumentException(
+ "The provider must implement javax.ws.rs.ext.MessageBodyWriter");
+ }
+ xmlWriter = (MessageBodyWriter)provider;
+
+ if (provider instanceof MessageBodyReader) {
+ xmlReader = (MessageBodyReader)provider;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> DataReader<T> createReader(final Class<T> cls) {
+ if (xmlReader == null) {
+ throw new IllegalStateException(
+ "javax.ws.rs.ext.MessageBodyReader reference is uninitialized");
+ }
+ return (DataReader<T>)new MessageBodyDataReader();
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> DataWriter<T> createWriter(final Class<T> cls) {
+ return (DataWriter<T>)new MessageBodyDataWriter();
+ }
+
+ public Class<?>[] getSupportedReaderFormats() {
+ return SUPPORTED_READER_FORMATS;
+ }
+
+ public Class<?>[] getSupportedWriterFormats() {
+ return SUPPORTED_WRITER_FORMATS;
+ }
+
+ public void initialize(Service service) {
+ // Check how to deal with individual parts if needed, build a single JAXBContext, etc
+ }
+
+
+ // TODO: The method containing the actual annotations have to retrieved
+ protected Method getTargetMethod(Message m) {
+ BindingOperationInfo bop = m.getExchange().get(BindingOperationInfo.class);
+ MethodDispatcher md = (MethodDispatcher)
+ m.getExchange().get(Service.class).get(MethodDispatcher.class.getName());
+ return md.getMethod(bop);
+ }
+
+ @SuppressWarnings("unchecked")
+ private MultivaluedMap<String, String> getHeaders(Message message) {
+ return new MetadataMap<String, String>(
+ (Map<String, List<String>>)message.get(Message.PROTOCOL_HEADERS), true, true);
+ }
+
+ private class MessageBodyDataWriter implements DataWriter<XMLStreamWriter> {
+
+ public void write(Object obj, XMLStreamWriter output) {
+ write(obj, null, output);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void write(Object obj, MessagePartInfo part, XMLStreamWriter output) {
+ try {
+ Message message = PhaseInterceptorChain.getCurrentMessage();
+ Method method = getTargetMethod(message);
+ MultivaluedMap<String, String> headers = getHeaders(message);
+ xmlWriter.writeTo(obj,
+ method.getReturnType(),
+ method.getGenericReturnType(),
+ method.getAnnotations(),
+ MediaType.APPLICATION_XML_TYPE,
+ headers,
+ null);
+ message.put(Message.PROTOCOL_HEADERS, headers);
+ } catch (Exception ex) {
+ // ignore
+ }
+ }
+
+ public void setAttachments(Collection<Attachment> attachments) {
+ // complete
+ }
+
+ public void setProperty(String key, Object value) {
+ // complete
+ }
+
+ public void setSchema(Schema s) {
+ // complete
+ }
+ }
+
+ private class MessageBodyDataReader implements DataReader<XMLStreamReader> {
+
+ public Object read(XMLStreamReader input) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object read(MessagePartInfo part, XMLStreamReader input) {
+ return doRead(part.getTypeClass(), input);
+ }
+
+ public Object read(QName elementQName, XMLStreamReader input, Class type) {
+ return doRead(type, input);
+ }
+
+
+ @SuppressWarnings("unchecked")
+ private Object doRead(Class cls, XMLStreamReader input) {
+ try {
+ Message message = PhaseInterceptorChain.getCurrentMessage();
+ Method method = getTargetMethod(message);
+ return xmlReader.readFrom(cls,
+ method.getGenericParameterTypes()[0],
+ method.getParameterTypes()[0].getAnnotations(),
+ MediaType.APPLICATION_ATOM_XML_TYPE,
+ getHeaders(message),
+ null);
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+ public void setAttachments(Collection<Attachment> attachments) {
+ // complete
+ }
+
+ public void setProperty(String prop, Object value) {
+ // complete
+ }
+
+ public void setSchema(Schema s) {
+ // complete
+ }
+
+ };
+}
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXRSDataBinding.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXRSDataBinding.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java?rev=1054645&r1=1054644&r2=1054645&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java Mon Jan 3 15:17:54 2011
@@ -110,6 +110,24 @@ public class JAXRSSoapBookTest extends A
useHelloService(hw);
}
+ @Test
+ public void testHelloSoapCustomDataBinding() throws Exception {
+ final QName serviceName = new QName("http://hello.com", "HelloWorld");
+ final QName portName = new QName("http://hello.com", "HelloWorldPort");
+ final String address = "http://localhost:" + PORT + "/test/services/hello-soap-databinding";
+
+ Service service = Service.create(serviceName);
+ service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, address);
+
+ HelloWorld hw = service.getPort(HelloWorld.class);
+
+ User user = new UserImpl("Barry");
+ User user2 = hw.echoUser(user);
+
+ assertNotSame(user, user2);
+ assertEquals("Barry", user.getName());
+ }
+
private void useHelloService(HelloWorld service) {
assertEquals("Hello Barry", service.sayHi("Barry"));
assertEquals("Hello Fred", service.sayHiToUser(new UserImpl("Fred")));
Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorld.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorld.java?rev=1054645&r1=1054644&r2=1054645&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorld.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorld.java Mon Jan 3 15:17:54 2011
@@ -20,6 +20,8 @@ package org.apache.cxf.systest.jaxrs.jax
import java.util.Map;
+import javax.jws.WebParam;
+import javax.jws.WebResult;
import javax.jws.WebService;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -54,4 +56,11 @@ public interface HelloWorld {
@Consumes("text/xml")
@XmlJavaTypeAdapter(IntegerUserMapAdapter.class)
Map<Integer, User> echoUsers(@XmlJavaTypeAdapter(IntegerUserMapAdapter.class) Map<Integer, User> users);
+
+ @POST
+ @Produces("text/xml")
+ @Consumes("text/xml")
+ @Path("user")
+ @WebResult(name = "User")
+ User echoUser(@WebParam(name = "User") User user);
}
Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorldImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorldImpl.java?rev=1054645&r1=1054644&r2=1054645&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorldImpl.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/jaxws/HelloWorldImpl.java Mon Jan 3 15:17:54 2011
@@ -50,5 +50,9 @@ public class HelloWorldImpl implements H
return us;
}
+ public User echoUser(User user) {
+ return user;
+ }
+
}
// END SNIPPET: service
Modified: cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_soap_rest/WEB-INF/beans.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_soap_rest/WEB-INF/beans.xml?rev=1054645&r1=1054644&r2=1054645&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_soap_rest/WEB-INF/beans.xml (original)
+++ cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_soap_rest/WEB-INF/beans.xml Mon Jan 3 15:17:54 2011
@@ -73,7 +73,7 @@ http://cxf.apache.org/schemas/jaxrs.xsd"
<jaxrs:server id="hello_rest" address="/hello-rest">
<jaxrs:serviceBeans>
<bean class="org.apache.cxf.systest.jaxrs.jaxws.HelloWorldImpl"/>
- </jaxrs:serviceBeans>
+ </jaxrs:serviceBeans>
</jaxrs:server>
<jaxws:endpoint xmlns:s="http://hello.com"
@@ -92,7 +92,26 @@ http://cxf.apache.org/schemas/jaxrs.xsd"
<jaxws:properties>
<entry key="org.apache.cxf.endpoint.private" value="true"/>
</jaxws:properties>
- </jaxws:endpoint>
+ </jaxws:endpoint>
+
+ <jaxws:endpoint xmlns:s="http://hello.com"
+ serviceName="s:HelloWorld"
+ endpointName="s:HelloWorldPort"
+ id="hello_soap-databinding"
+ implementor="org.apache.cxf.systest.jaxrs.jaxws.HelloWorldImpl"
+ address="/hello-soap-databinding">
+
+ <jaxws:dataBinding>
+ <ref bean="jaxrs-data-binding"/>
+ </jaxws:dataBinding>
+
+ </jaxws:endpoint>
+
+ <bean id="jaxrs-data-binding" class="org.apache.cxf.jaxrs.provider.JAXRSDataBinding">
+ <property name="provider" ref="jaxbProviderSoap"/>
+ </bean>
+
+ <bean id="jaxbProviderSoap" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider"/>
<jaxrs:server id="restservice2"
address="/rest2">
@@ -109,7 +128,7 @@ http://cxf.apache.org/schemas/jaxrs.xsd"
</jaxrs:serviceBeans>
<jaxrs:providers>
- <ref bean="jaxbProvider" />
+ <ref bean="jaxbProviderFI" />
</jaxrs:providers>
<jaxrs:properties>
@@ -124,7 +143,7 @@ http://cxf.apache.org/schemas/jaxrs.xsd"
</jaxrs:serviceBeans>
<jaxrs:providers>
- <ref bean="jaxbProvider" />
+ <ref bean="jaxbProviderFI" />
</jaxrs:providers>
</jaxrs:server>
@@ -135,7 +154,7 @@ http://cxf.apache.org/schemas/jaxrs.xsd"
</jaxrs:serviceBeans>
<jaxrs:providers>
- <ref bean="jaxbProvider" />
+ <ref bean="jaxbProviderFI" />
</jaxrs:providers>
<jaxrs:properties>
@@ -143,7 +162,7 @@ http://cxf.apache.org/schemas/jaxrs.xsd"
</jaxrs:properties>
</jaxrs:server>
- <bean id="jaxbProvider" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
+ <bean id="jaxbProviderFI" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
<property name="produceMediaTypes" ref="fastinfosetType"/>
<property name="consumeMediaTypes" ref="fastinfosetType"/>
</bean>