From d43b880637d25eacf304c29ec5a00ebbc8c61019 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 23 Apr 2014 14:21:45 +0200 Subject: [PATCH] WS-Addressing EMs support SmartEndpointInterceptor All WS-Addressing EndpointsMappings now support endpoint interceptors registered via a block (i.e. SmartEndpointInteceptors). Issue: SWS-874 --- .../server/AbstractActionEndpointMapping.java | 15 +--- .../AbstractAddressingEndpointMapping.java | 68 ++++++++++++++----- ...tationActionMethodEndpointMappingTest.java | 60 +++++++--------- 3 files changed, 79 insertions(+), 64 deletions(-) diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionEndpointMapping.java index 0a2888a09..3765bcead 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractActionEndpointMapping.java @@ -21,8 +21,6 @@ import java.util.Map; import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; import org.springframework.util.Assert; import org.springframework.ws.soap.addressing.core.MessageAddressingProperties; @@ -37,8 +35,7 @@ * @author Arjen Poutsma * @since 1.5.0 */ -public abstract class AbstractActionEndpointMapping extends AbstractAddressingEndpointMapping - implements ApplicationContextAware { +public abstract class AbstractActionEndpointMapping extends AbstractAddressingEndpointMapping { /** The defaults suffix to add to the request {@code Action} for reply messages. */ public static final String DEFAULT_OUTPUT_ACTION_SUFFIX = "Response"; @@ -53,7 +50,6 @@ public abstract class AbstractActionEndpointMapping extends AbstractAddressingEn private String faultActionSuffix = DEFAULT_OUTPUT_ACTION_SUFFIX; - private ApplicationContext applicationContext; /** Returns the suffix to add to request {@code Action}s for reply messages. */ public String getOutputActionSuffix() { @@ -85,11 +81,6 @@ public void setFaultActionSuffix(String faultActionSuffix) { this.faultActionSuffix = faultActionSuffix; } - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - @Override protected final Object getEndpointInternal(MessageAddressingProperties map) { URI action = map.getAction(); @@ -143,8 +134,8 @@ protected void registerEndpoint(URI action, Object endpoint) throws BeansExcepti if (endpoint instanceof String) { String endpointName = (String) endpoint; - if (applicationContext.isSingleton(endpointName)) { - resolvedEndpoint = applicationContext.getBean(endpointName); + if (getApplicationContext().isSingleton(endpointName)) { + resolvedEndpoint = getApplicationContext().getBean(endpointName); } } Object mappedEndpoint = this.endpointMap.get(action); diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractAddressingEndpointMapping.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractAddressingEndpointMapping.java index e8896d389..943254646 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractAddressingEndpointMapping.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/server/AbstractAddressingEndpointMapping.java @@ -17,17 +17,25 @@ package org.springframework.ws.soap.addressing.server; import java.net.URI; +import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; +import java.util.List; +import java.util.Map; import javax.xml.transform.TransformerException; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.core.Ordered; import org.springframework.util.Assert; import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointInterceptor; import org.springframework.ws.server.EndpointInvocationChain; import org.springframework.ws.server.EndpointMapping; +import org.springframework.ws.server.SmartEndpointInterceptor; import org.springframework.ws.soap.SoapHeader; import org.springframework.ws.soap.SoapHeaderElement; import org.springframework.ws.soap.SoapMessage; @@ -64,7 +72,7 @@ * @since 1.5.0 */ public abstract class AbstractAddressingEndpointMapping extends TransformerObjectSupport - implements SoapEndpointMapping, InitializingBean, Ordered { + implements SoapEndpointMapping, ApplicationContextAware, InitializingBean, Ordered { private String[] actorsOrRoles; @@ -80,6 +88,11 @@ public abstract class AbstractAddressingEndpointMapping extends TransformerObjec private EndpointInterceptor[] postInterceptors = new EndpointInterceptor[0]; + private SmartEndpointInterceptor[] smartInterceptors = + new SmartEndpointInterceptor[0]; + + private ApplicationContext applicationContext; + private int order = Integer.MAX_VALUE; // default: same as non-Ordered @@ -115,7 +128,17 @@ public final void setUltimateReceiver(boolean ultimateReceiver) { this.isUltimateReceiver = ultimateReceiver; } - @Override + public ApplicationContext getApplicationContext() { + return applicationContext; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } + + @Override public final int getOrder() { return order; } @@ -210,12 +233,21 @@ public final void setVersions(AddressingVersion[] versions) { this.versions = versions; } - @Override - public void afterPropertiesSet() throws Exception { - if (logger.isInfoEnabled()) { - logger.info("Supporting " + Arrays.asList(versions)); - } - } + @Override + public void afterPropertiesSet() throws Exception { + if (logger.isInfoEnabled()) { + logger.info("Supporting " + Arrays.asList(versions)); + } + if (getApplicationContext() != null) { + Map smartInterceptors = BeanFactoryUtils + .beansOfTypeIncludingAncestors(getApplicationContext(), + SmartEndpointInterceptor.class, true, false); + if (!smartInterceptors.isEmpty()) { + this.smartInterceptors = smartInterceptors.values() + .toArray(new SmartEndpointInterceptor[smartInterceptors.size()]); + } + } + } @Override public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws TransformerException { @@ -253,15 +285,17 @@ private EndpointInvocationChain getEndpointInvocationChain(Object endpoint, WebServiceMessageSender[] messageSenders = getMessageSenders(endpoint); MessageIdStrategy messageIdStrategy = getMessageIdStrategy(endpoint); - EndpointInterceptor[] interceptors = - new EndpointInterceptor[preInterceptors.length + postInterceptors.length + - 1]; - System.arraycopy(preInterceptors, 0, interceptors, 0, preInterceptors.length); - AddressingEndpointInterceptor interceptor = new AddressingEndpointInterceptor(version, messageIdStrategy, - messageSenders, responseAction, faultAction); - interceptors[preInterceptors.length] = interceptor; - System.arraycopy(postInterceptors, 0, interceptors, preInterceptors.length + 1, postInterceptors.length); - return new SoapEndpointInvocationChain(endpoint, interceptors, actorsOrRoles, isUltimateReceiver); + List interceptors = new ArrayList(preInterceptors.length + postInterceptors.length + smartInterceptors.length + 1); + AddressingEndpointInterceptor addressingInterceptor = new AddressingEndpointInterceptor(version, messageIdStrategy, + messageSenders, responseAction, faultAction); + + interceptors.addAll(Arrays.asList(preInterceptors)); + interceptors.add(addressingInterceptor); + interceptors.addAll(Arrays.asList(postInterceptors)); + interceptors.addAll(Arrays.asList(smartInterceptors)); + + return new SoapEndpointInvocationChain(endpoint, + interceptors.toArray(new EndpointInterceptor[interceptors.size()]), actorsOrRoles, isUltimateReceiver); } private boolean supports(AddressingVersion version, SoapMessage request) { diff --git a/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AnnotationActionMethodEndpointMappingTest.java b/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AnnotationActionMethodEndpointMappingTest.java index 891bac984..d4544cd41 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AnnotationActionMethodEndpointMappingTest.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AnnotationActionMethodEndpointMappingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2014 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. @@ -23,24 +23,24 @@ import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPException; +import org.custommonkey.xmlunit.XMLUnit; +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; + import org.springframework.context.support.StaticApplicationContext; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointInvocationChain; import org.springframework.ws.server.endpoint.MethodEndpoint; import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.server.endpoint.interceptor.DelegatingSmartEndpointInterceptor; +import org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor; import org.springframework.ws.soap.addressing.server.annotation.Action; import org.springframework.ws.soap.addressing.server.annotation.Address; import org.springframework.ws.soap.saaj.SaajSoapMessage; import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; -import org.custommonkey.xmlunit.XMLUnit; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; - public class AnnotationActionMethodEndpointMappingTest { private StaticApplicationContext applicationContext; @@ -55,31 +55,23 @@ public void setUp() throws Exception { XMLUnit.setIgnoreWhitespace(true); applicationContext = new StaticApplicationContext(); applicationContext.registerSingleton("mapping", AnnotationActionEndpointMapping.class); + applicationContext.registerSingleton("interceptor", MyInterceptor.class); + applicationContext.registerSingleton("endpoint", MyEndpoint.class); + applicationContext.refresh(); mapping = (AnnotationActionEndpointMapping) applicationContext.getBean("mapping"); } @Test - public void testNoAddress() throws Exception { - applicationContext.registerSingleton("endpoint", Endpoint1.class); - applicationContext.refresh(); + public void mapping() throws Exception { MessageContext messageContext = createMessageContext(); EndpointInvocationChain chain = mapping.getEndpoint(messageContext); - Assert.assertNotNull("MethodEndpoint not registered", chain); - MethodEndpoint expected = new MethodEndpoint(applicationContext.getBean("endpoint"), "doIt", new Class[0]); - Assert.assertEquals("Invalid endpoint registered", expected, chain.getEndpoint()); - } - - @Test - public void testAddress() throws Exception { - applicationContext.registerSingleton("endpoint", Endpoint2.class); - applicationContext.refresh(); - MessageContext messageContext = createMessageContext(); - - EndpointInvocationChain chain = mapping.getEndpoint(messageContext); - Assert.assertNotNull("MethodEndpoint not registered", chain); - MethodEndpoint expected = new MethodEndpoint(applicationContext.getBean("endpoint"), "doIt", new Class[0]); - Assert.assertEquals("Invalid endpoint registered", expected, chain.getEndpoint()); + assertNotNull("MethodEndpoint not registered", chain); + MethodEndpoint expected = new MethodEndpoint(applicationContext.getBean("endpoint"), "doIt"); + assertEquals("Invalid endpoint registered", expected, chain.getEndpoint()); + assertEquals("No smart interceptors registered", 2, chain.getInterceptors().length); + assertTrue(chain.getInterceptors()[0] instanceof AddressingEndpointInterceptor); + assertTrue(chain.getInterceptors()[1] instanceof MyInterceptor); } private MessageContext createMessageContext() throws SOAPException, IOException { @@ -97,7 +89,8 @@ private MessageContext createMessageContext() throws SOAPException, IOException } @Endpoint - private static class Endpoint1 { + @Address("mailto:joe@fabrikam123.example") + private static class MyEndpoint { @Action("http://fabrikam123.example/mail/Delete") public void doIt() { @@ -105,13 +98,10 @@ public void doIt() { } } - @Endpoint - @Address("mailto:joe@fabrikam123.example") - private static class Endpoint2 { + private static class MyInterceptor extends DelegatingSmartEndpointInterceptor { - @Action("http://fabrikam123.example/mail/Delete") - public void doIt() { - - } - } + public MyInterceptor() { + super(new PayloadLoggingInterceptor()); + } + } } \ No newline at end of file