INT-2720: UriTemplate Support for S-WS Transports

Remove deprecation in the WS module

JIRA: https://jira.springsource.org/browse/INT-2720
      https://jira.springsource.org/browse/INT-2530

INT-2720: Polishing after rebase

INT-2720: Add a note to the Reference Manual

Polishing <authorgroup> to avoid extra whitespace before name

INT-2720: Pr comments & polishing

* Revert removed public API
* Revert tabs in What's new
* Change real URL to fake to allow for tests to work off-line
* Add smackx dependency to avoid error messages in logs
This commit is contained in:
Artem Bilan
2012-08-27 17:59:06 +03:00
committed by Gary Russell
parent 7d99a9a07a
commit 6b7ae6ceed
11 changed files with 332 additions and 166 deletions

View File

@@ -16,6 +16,10 @@
package org.springframework.integration.ws;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
@@ -43,8 +47,6 @@ import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageSender;
import static org.junit.Assert.*;
/**
* @author Mark Fisher
* @author Artem Bilan

View File

@@ -1,17 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ws="http://www.springframework.org/schema/integration/ws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ws="http://www.springframework.org/schema/integration/ws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/ws
http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd">
<ws:outbound-gateway id="gateway" request-channel="input" uri="http://springsource.org/{foo}-{bar}" interceptor="interceptor">
<ws:uri-variable name="foo" expression="payload.substring(1,7)"/>
<ws:uri-variable name="bar" expression="headers.x"/>
</ws:outbound-gateway>
<bean id="interceptor" class="org.springframework.integration.ws.config.UriVariableTests$TestClientInterceptor"/>
<!--HTTP Transport-->
<ws:outbound-gateway request-channel="inputHttp"
uri="http://test.org/{foo}-{bar}?param={param}"
interceptor="interceptor">
<ws:uri-variable name="foo" expression="payload.substring(1,7)"/>
<ws:uri-variable name="bar" expression="headers.x"/>
<ws:uri-variable name="param" expression="headers.param"/>
</ws:outbound-gateway>
<!--JMS Transport-->
<ws:outbound-gateway request-channel="inputJms"
uri="jms:{destination}?deliveryMode={deliveryMode}&amp;priority={priority}"
interceptor="interceptor"
message-sender="jmsMessageSender">
<ws:uri-variable name="destination" expression="headers.jmsQueue"/>
<ws:uri-variable name="deliveryMode" expression="headers.deliveryMode"/>
<ws:uri-variable name="priority" expression="headers.jms_priority"/>
</ws:outbound-gateway>
<bean id="jmsMessageSender" class="org.mockito.Mockito" factory-method="spy">
<constructor-arg>
<bean class="org.springframework.ws.transport.jms.JmsMessageSender">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
</constructor-arg>
</bean>
<bean id="jmsConnectionFactory" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="javax.jms.ConnectionFactory"/>
</bean>
<!--Email Transport-->
<ws:outbound-gateway request-channel="inputEmail"
uri="mailto:{to}?subject={subject}"
interceptor="emailInterceptor"
message-sender="emailMessageSender">
<ws:uri-variable name="to" expression="headers.to"/>
<ws:uri-variable name="subject" expression="headers.subject"/>
</ws:outbound-gateway>
<bean id="emailMessageSender" class="org.springframework.ws.transport.mail.MailMessageSender">
<property name="from" value="spring-integration-ws SOAP Client &lt;client@example.com&gt;"/>
<property name="transportUri" value="smtp://client:s04p@smtp.example.com"/>
<property name="storeUri" value="imap://client:s04p@imap.example.com/INBOX"/>
</bean>
<bean id="emailInterceptor" class="org.springframework.integration.ws.config.UriVariableTests$Int2720EmailTestClientInterceptor"/>
<!--XMPP Transport-->
<ws:outbound-gateway request-channel="inputXmpp"
uri="xmpp:{user}@jabber.org"
interceptor="interceptor"
message-sender="xmppMessageSender">
<ws:uri-variable name="user" expression="headers.to"/>
</ws:outbound-gateway>
<bean id="xmppMessageSender" class="org.springframework.ws.transport.xmpp.XmppMessageSender">
<property name="connection" ref="xmppConnection"/>
</bean>
<bean id="xmppConnection" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="org.jivesoftware.smack.XMPPConnection"/>
</bean>
</beans>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2013 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.
@@ -19,31 +19,48 @@ package org.springframework.integration.ws.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Packet;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessageHandlingException;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.ws.client.WebServiceClientException;
import org.springframework.ws.client.WebServiceIOException;
import org.springframework.ws.client.WebServiceTransportException;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessageCreationException;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.ws.transport.context.TransportContext;
import org.springframework.ws.transport.context.TransportContextHolder;
import org.springframework.ws.transport.http.HttpUrlConnection;
import org.springframework.ws.transport.mail.MailSenderConnection;
/**
* @author Mark Fisher
* @author Artem Bilan
* @since 2.1
*/
@RunWith(SpringJUnit4ClassRunner.class)
@@ -51,15 +68,40 @@ import org.springframework.ws.transport.http.HttpUrlConnection;
public class UriVariableTests {
@Autowired
private ApplicationContext context;
private TestClientInterceptor interceptor;
@Autowired
private MessageChannel inputHttp;
@Autowired
private MessageChannel inputJms;
@Autowired
private WebServiceMessageSender jmsMessageSender;
@Autowired
private ConnectionFactory jmsConnectionFactory;
@Autowired
private MessageChannel inputXmpp;
@Autowired
private XMPPConnection xmppConnection;
@Autowired
private MessageChannel inputEmail;
@Autowired
private Int2720EmailTestClientInterceptor emailInterceptor;
@Test
public void checkUriVariables() {
MessageChannel input = context.getBean("input", MessageChannel.class);
TestClientInterceptor interceptor = context.getBean("interceptor", TestClientInterceptor.class);
Message<?> message = MessageBuilder.withPayload("<spring/>").setHeader("x", "integration").build();
public void testHttpUriVariables() {
Message<?> message = MessageBuilder.withPayload("<spring/>")
.setHeader("x", "integration")
.setHeader("param", "test1 & test2")
.build();
try {
input.send(message);
this.inputHttp.send(message);
}
catch (MessageHandlingException e) {
// expected
@@ -67,30 +109,117 @@ public class UriVariableTests {
assertTrue(WebServiceIOException.class.equals(causeType) // offline
|| SoapMessageCreationException.class.equals(causeType));
}
assertEquals("http://springsource.org/spring-integration", interceptor.getLastUri().toString());
assertEquals("http://test.org/spring-integration?param=test1%20%26%20test2", this.interceptor.getLastUri().toString());
}
@Test
public void testInt2720JmsUriVariables() throws JMSException, IOException {
final String destinationName = "SPRING.INTEGRATION.QUEUE";
Queue queue = Mockito.mock(Queue.class);
// Need for 'QueueSession#createQueue()'
Mockito.when(queue.getQueueName()).thenReturn(destinationName);
Session session = Mockito.mock(Session.class);
Mockito.when(session.createQueue(Mockito.anyString())).thenReturn(queue);
Mockito.when(session.createBytesMessage()).thenReturn(Mockito.mock(BytesMessage.class));
MessageProducer producer = Mockito.mock(MessageProducer.class);
Mockito.when(session.createProducer(queue)).thenReturn(producer);
// For this test it's enough to not go ahead. Invoked in the 'JmsSenderConnection#onSendAfterWrite' on the
// 'WebServiceTemplate#sendRequest' after invocation of our 'TestClientInterceptor'
Mockito.when(session.createTemporaryQueue()).thenThrow(new WebServiceIOException("intentional"));
Connection connection = Mockito.mock(Connection.class);
Mockito.when(connection.createSession(Mockito.anyBoolean(), Mockito.anyInt())).thenReturn(session);
Mockito.when(this.jmsConnectionFactory.createConnection()).thenReturn(connection);
Message<?> message = MessageBuilder.withPayload("<spring/>")
.setHeader("jmsQueue", destinationName)
.setHeader("deliveryMode", "NON_PERSISTENT")
.setHeader("jms_priority", "5")
.build();
try {
this.inputJms.send(message);
}
catch (MessageHandlingException e) {
// expected
Class<?> causeType = e.getCause().getClass();
assertTrue(WebServiceIOException.class.equals(causeType)); // offline
}
URI uri = URI.create("jms:SPRING.INTEGRATION.QUEUE?deliveryMode=NON_PERSISTENT&priority=5");
Mockito.verify(this.jmsMessageSender).createConnection(uri);
Mockito.verify(session).createQueue(destinationName);
assertEquals("jms:" + destinationName, this.interceptor.getLastUri().toString());
Mockito.verify(producer).setDeliveryMode(DeliveryMode.NON_PERSISTENT);
Mockito.verify(producer).setPriority(5);
}
@Test
public void testInt2720EmailUriVariables() {
final String testEmailTo = "user@example.com";
final String testEmailSubject = "Test subject";
Message<?> message = MessageBuilder.withPayload("<spring/>")
.setHeader("to", testEmailTo)
.setHeader("subject", testEmailSubject)
.build();
try {
this.inputEmail.send(message);
}
catch (MessageHandlingException e) {
// expected
Class<?> causeType = e.getCause().getClass();
assertTrue(WebServiceTransportException.class.equals(causeType)); // offline
}
WebServiceConnection webServiceConnection = this.emailInterceptor.getLastWebServiceConnection();
assertEquals(testEmailTo, TestUtils.getPropertyValue(webServiceConnection, "to").toString());
assertEquals(testEmailSubject, TestUtils.getPropertyValue(webServiceConnection, "subject"));
assertEquals("mailto:user@example.com?subject=Test%20subject", this.emailInterceptor.getLastUri().toString());
}
@Test
public void testInt2720XmppUriVariables() {
Mockito.doThrow(new WebServiceIOException("intentional")).when(this.xmppConnection).sendPacket(Mockito.any(Packet.class));
Message<?> message = MessageBuilder.withPayload("<spring/>").setHeader("to", "user").build();
try {
this.inputXmpp.send(message);
}
catch (MessageHandlingException e) {
// expected
Class<?> causeType = e.getCause().getClass();
assertTrue(WebServiceIOException.class.equals(causeType)); // offline
}
ArgumentCaptor<Packet> argument = ArgumentCaptor.forClass(Packet.class);
Mockito.verify(this.xmppConnection).sendPacket(argument.capture());
assertEquals("user@jabber.org", argument.getValue().getTo());
assertEquals("xmpp:user@jabber.org", this.interceptor.getLastUri().toString());
}
private static class TestClientInterceptor implements ClientInterceptor {
private URI lastUri;
private volatile URI lastUri;
private URI getLastUri() {
public URI getLastUri() {
return this.lastUri;
}
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
TransportContext tc = TransportContextHolder.getTransportContext();
if (tc != null && tc.getConnection() instanceof HttpUrlConnection) {
if (tc != null) {
try {
this.lastUri = ((HttpUrlConnection) tc.getConnection()).getUri();
this.lastUri = tc.getConnection().getUri();
}
catch (URISyntaxException e) {
throw new IllegalStateException(e);
}
}
else {
throw new IllegalStateException("expected HttpUrlConnection as TransportContext");
throw new IllegalStateException("expected WebServiceConnection in the TransportContext");
}
return false;
}
@@ -104,4 +233,27 @@ public class UriVariableTests {
}
}
private static class Int2720EmailTestClientInterceptor extends TestClientInterceptor {
private volatile WebServiceConnection webServiceConnection;
public WebServiceConnection getLastWebServiceConnection() {
return webServiceConnection;
}
@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
TransportContext tc = TransportContextHolder.getTransportContext();
WebServiceConnection webServiceConnection = tc.getConnection();
if (webServiceConnection instanceof MailSenderConnection) {
this.webServiceConnection = webServiceConnection;
}
else {
throw new IllegalStateException("expected MailSenderConnection in the TransportContext");
}
return super.handleRequest(messageContext);
}
}
}

View File

@@ -18,7 +18,6 @@ package org.springframework.integration.ws.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.net.URI;
@@ -43,11 +42,11 @@ import org.springframework.integration.ws.SimpleWebServiceOutboundGateway;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.web.util.UriTemplate;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.SourceExtractor;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.support.destination.DestinationProvider;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.transport.WebServiceMessageSender;
@@ -399,9 +398,9 @@ public class WebServiceOutboundGatewayParserTests {
AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithJmsUri");
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
MessageHandler handler = TestUtils.getPropertyValue(endpoint, "handler", MessageHandler.class);
DestinationProvider destinationProvider = TestUtils.getPropertyValue(handler, "destinationProvider", DestinationProvider.class);
assertNotNull(destinationProvider);
assertEquals(URI.create("jms:wsQueue"), destinationProvider.getDestination());
assertNull(TestUtils.getPropertyValue(handler, "destinationProvider"));
UriTemplate uriTemplate = TestUtils.getPropertyValue(handler, "uriTemplate", UriTemplate.class);
assertEquals(URI.create("jms:wsQueue"), uriTemplate.expand());
}
@Test(expected = BeanDefinitionParsingException.class)