- Split out WS-Addressing to multiple packages (SWS-84)

- Javadoc
This commit is contained in:
Arjen Poutsma
2008-02-23 18:30:51 +00:00
parent de63de8c78
commit 249a5a8309
6 changed files with 188 additions and 112 deletions

View File

@@ -1,94 +0,0 @@
/*
* Copyright 2008 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.ws.soap.addressing;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.server.endpoint.MethodEndpoint;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.soap.addressing.annotation.Action;
import org.springframework.ws.soap.addressing.annotation.Address;
/**
* @author Arjen Poutsma
* @since 1.5.0
*/
public class AnnotationActionMethodEndpointMapping extends AbstractActionMethodEndpointMapping
implements BeanPostProcessor {
/** Returns the 'endpoint' annotation type. Default is {@link Endpoint}. */
protected Class<? extends Annotation> getEndpointAnnotationType() {
return Endpoint.class;
}
public final Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public final Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (getEndpointClass(bean).getAnnotation(getEndpointAnnotationType()) != null) {
registerMethods(bean);
}
return bean;
}
protected URI getActionForMethod(Method method) {
Action action = method.getAnnotation(Action.class);
if (action != null) {
try {
return new URI(action.value());
}
catch (URISyntaxException e) {
// ignore
}
}
return null;
}
protected Object getEndpointInternal(URI to, URI action) {
MethodEndpoint methodEndpoint = (MethodEndpoint) lookupEndpoint(action);
if (methodEndpoint != null) {
// respect the Address annotation, if set
Class endpointClass = methodEndpoint.getMethod().getDeclaringClass();
Address address = AnnotationUtils.findAnnotation(endpointClass, Address.class);
if (address != null && StringUtils.hasText(address.value())) {
try {
URI addressUri = new URI(address.value());
if (to.equals(addressUri)) {
return methodEndpoint;
}
}
catch (URISyntaxException e) {
throw new IllegalArgumentException(
"Invalid Address annotation [" + address.value() + "] on [" + endpointClass + "]");
}
}
else {
// address not set
return methodEndpoint;
}
}
return null;
}
}

View File

@@ -37,10 +37,4 @@ public @interface Action {
/** Signifies the value for the request WS-Addressing <code>Action</code> header that is handled by the method. */
String value();
/**
* Explicit value of the WS-Addressing <code>Action</code> message addressing property for the <code>output</code>
* message of the operation.
*/
String output() default "";
}

View File

@@ -24,11 +24,8 @@ import java.lang.annotation.Target;
/**
* Marks an endpoint with a WS-Addressing <code>Address</code>. If this annotation is applied, the {@link #value()} is
* compared to the {@link org.springframework.ws.soap.addressing.MessageAddressingProperties#getTo() destination}
* compared to the {@link org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getTo() destination}
* property of the incominging message.
* <p/>
* as the handler for an incoming request. The annotation value signifies the value for the request WS-Addressing
* <code>Action</code> header that is handled by the method.
*
* @author Arjen Poutsma
* @since 1.5.0

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2008 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.ws.soap.addressing.server;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.JdkVersion;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.server.endpoint.MethodEndpoint;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.soap.addressing.annotation.Action;
import org.springframework.ws.soap.addressing.annotation.Address;
/**
* Implementation of the {@link org.springframework.ws.server.EndpointMapping} interface that uses the {@link Action}
* annotation to map methods to a WS-Addressing <code>Action</code> header.
* <p/>
* Endpoints typically have the following form:
* <pre>
* &#64;Endpoint
* &#64;Address("mailto:joe@fabrikam123.example")
* public class MyEndpoint{
* &#64;Action("http://fabrikam123.example/mail/Delete")
* public Source doSomethingWithRequest() {
* ...
* }
* }
* </pre>
* <p/>
* If set, the {@link @Address} annotation on the endpoint class should be equal to the {@link
* org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getTo() destination} property of the
* incominging message.
*
* @author Arjen Poutsma
* @see Action
* @see Address
* @since 1.5.0
*/
public class AnnotationActionEndpointMapping extends AbstractActionEndpointMapping implements BeanPostProcessor {
/** Returns the 'endpoint' annotation type. Default is {@link Endpoint}. */
protected Class<? extends Annotation> getEndpointAnnotationType() {
return Endpoint.class;
}
public final Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public final Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (AopUtils.getTargetClass(bean).getAnnotation(getEndpointAnnotationType()) != null) {
registerMethods(bean);
}
return bean;
}
/**
* Helper method that registers the methods of the given bean. This method iterates over the methods of the bean,
* and calls {@link #getActionForMethod(java.lang.reflect.Method)} for each. If this returns a URI, the method is
* registered using {@link #registerEndpoint(java.net.URI, Object)}.
*
* @see #getActionForMethod (java.lang.reflect.Method)
*/
protected void registerMethods(Object endpoint) {
Assert.notNull(endpoint, "'endpoint' must not be null");
Method[] methods = AopUtils.getTargetClass(endpoint).getMethods();
for (int i = 0; i < methods.length; i++) {
if (JdkVersion.isAtLeastJava15() && methods[i].isSynthetic() ||
methods[i].getDeclaringClass().equals(Object.class)) {
continue;
}
URI action = getActionForMethod(methods[i]);
if (action != null) {
registerEndpoint(action, new MethodEndpoint(endpoint, methods[i]));
}
}
}
/**
* Returns the action value for the specified method. Default implementation looks for the {@link Action} annotation
* value.
*/
protected URI getActionForMethod(Method method) {
Action action = method.getAnnotation(Action.class);
if (action != null && StringUtils.hasText(action.value())) {
try {
return new URI(action.value());
}
catch (URISyntaxException e) {
// ignore
}
}
return null;
}
/**
* Returns the address property of the given {@link MethodEndpoint}, by looking for the {@link Address} annotation.
* The value of this property should match the {@link org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getTo()
* destination} of incoming messages. Returns <code>null</code> if the anotation is not present, thus ignoring the
* destination property.
*
* @param endpoint the method endpoint to return the address for
* @return the endpoint address; or <code>null</code> to ignore the destination property
*/
protected URI getEndpointAddress(Object endpoint) {
MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint;
Class endpointClass = methodEndpoint.getMethod().getDeclaringClass();
Address address = AnnotationUtils.findAnnotation(endpointClass, Address.class);
if (address != null && StringUtils.hasText(address.value())) {
try {
return new URI(address.value());
}
catch (URISyntaxException e) {
throw new IllegalArgumentException(
"Invalid Address annotation [" + address.value() + "] on [" + endpointClass + "]");
}
}
return null;
}
}

View File

@@ -14,11 +14,18 @@
* limitations under the License.
*/
package org.springframework.ws.soap.addressing;
package org.springframework.ws.soap.addressing.server;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPException;
import org.custommonkey.xmlunit.XMLTestCase;
import org.custommonkey.xmlunit.XMLUnit;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
@@ -30,16 +37,20 @@ import org.springframework.ws.soap.addressing.annotation.Address;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
public class AnnotationActionMethodEndpointMappingTest extends AbstractWsAddressingTestCase {
public class AnnotationActionMethodEndpointMappingTest extends XMLTestCase {
private StaticApplicationContext applicationContext;
private AnnotationActionMethodEndpointMapping mapping;
private AnnotationActionEndpointMapping mapping;
protected void onSetUp() throws Exception {
private MessageFactory messageFactory;
protected void setUp() throws Exception {
messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
XMLUnit.setIgnoreWhitespace(true);
applicationContext = new StaticApplicationContext();
applicationContext.registerSingleton("mapping", AnnotationActionMethodEndpointMapping.class);
mapping = (AnnotationActionMethodEndpointMapping) applicationContext.getBean("mapping");
applicationContext.registerSingleton("mapping", AnnotationActionEndpointMapping.class);
mapping = (AnnotationActionEndpointMapping) applicationContext.getBean("mapping");
}
public void testNoAddress() throws Exception {
@@ -65,8 +76,17 @@ public class AnnotationActionMethodEndpointMappingTest extends AbstractWsAddress
}
private MessageContext createMessageContext() throws SOAPException, IOException {
SaajSoapMessage message = loadSaajMessage("200408/valid.xml");
return new DefaultMessageContext(message, new SaajSoapMessageFactory(messageFactory));
MimeHeaders mimeHeaders = new MimeHeaders();
mimeHeaders.addHeader("Content-Type", " application/soap+xml");
InputStream is = getClass().getResourceAsStream("valid.xml");
assertNotNull("Could not load valid.xml", is);
try {
SaajSoapMessage message = new SaajSoapMessage(messageFactory.createMessage(mimeHeaders, is));
return new DefaultMessageContext(message, new SaajSoapMessageFactory(messageFactory));
}
finally {
is.close();
}
}
@Endpoint

View File

@@ -0,0 +1,17 @@
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:f123="http://www.fabrikam123.example/svc53">
<S:Header>
<wsa:MessageID>uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://example.com/business/client1</wsa:Address>
</wsa:ReplyTo>
<wsa:To S:mustUnderstand="true">mailto:joe@fabrikam123.example</wsa:To>
<wsa:Action>http://fabrikam123.example/mail/Delete</wsa:Action>
</S:Header>
<S:Body>
<f123:Delete>
<maxCount>42</maxCount>
</f123:Delete>
</S:Body>
</S:Envelope>