/*
* Copyright 2002-2016 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.amqp.remoting;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Before;
import org.junit.Test;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Address;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.remoting.client.AmqpProxyFactoryBean;
import org.springframework.amqp.remoting.service.AmqpInvokerServiceExporter;
import org.springframework.amqp.remoting.testhelper.AbstractAmqpTemplate;
import org.springframework.amqp.remoting.testhelper.SentSavingTemplate;
import org.springframework.amqp.remoting.testservice.GeneralException;
import org.springframework.amqp.remoting.testservice.SpecialException;
import org.springframework.amqp.remoting.testservice.TestServiceImpl;
import org.springframework.amqp.remoting.testservice.TestServiceInterface;
import org.springframework.amqp.support.converter.MessageConversionException;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.remoting.RemoteProxyFailureException;
import org.springframework.remoting.support.RemoteInvocation;
/**
* @author David Bilge
* @author Artem Bilan
* @author Gary Russell
* @since 1.2
*/
public class RemotingTest {
private TestServiceInterface riggedProxy;
private AmqpInvokerServiceExporter serviceExporter;
/**
* Set up a rig of directly wired-up proxy and service listener so that both can be tested together without needing
* a running rabbit.
*/
@Before
public void initializeTestRig() throws Exception {
// Set up the service
TestServiceInterface testService = new TestServiceImpl();
this.serviceExporter = new AmqpInvokerServiceExporter();
final SentSavingTemplate sentSavingTemplate = new SentSavingTemplate();
this.serviceExporter.setAmqpTemplate(sentSavingTemplate);
this.serviceExporter.setService(testService);
this.serviceExporter.setServiceInterface(TestServiceInterface.class);
// Set up the client
AmqpProxyFactoryBean amqpProxyFactoryBean = new AmqpProxyFactoryBean();
amqpProxyFactoryBean.setServiceInterface(TestServiceInterface.class);
AmqpTemplate directForwardingTemplate = new AbstractAmqpTemplate() {
@Override
public Object convertSendAndReceive(Object payload) throws AmqpException {
Object[] arguments = ((RemoteInvocation) payload).getArguments();
if (arguments.length == 1 && arguments[0].equals("timeout")) {
return null;
}
MessageConverter messageConverter = serviceExporter.getMessageConverter();
Address replyTo = new Address("fakeExchangeName", "fakeRoutingKey");
MessageProperties messageProperties = new MessageProperties();
messageProperties.setReplyToAddress(replyTo);
Message message = messageConverter.toMessage(payload, messageProperties);
serviceExporter.onMessage(message);
Message resultMessage = sentSavingTemplate.getLastMessage();
return messageConverter.fromMessage(resultMessage);
}
};
amqpProxyFactoryBean.setAmqpTemplate(directForwardingTemplate);
amqpProxyFactoryBean.afterPropertiesSet();
Object rawProxy = amqpProxyFactoryBean.getObject();
riggedProxy = (TestServiceInterface) rawProxy;
}
@Test
public void testEcho() {
assertEquals("Echo Test", riggedProxy.simpleStringReturningTestMethod("Test"));
}
@Test
public void testSimulatedTimeout() throws Exception {
try {
this.riggedProxy.simulatedTimeoutMethod("timeout");
}
catch (RemoteProxyFailureException e) {
assertThat(e.getMessage(), containsString("'simulatedTimeoutMethod' with arguments '[timeout]'"));
}
}
@Test(expected = RuntimeException.class)
public void testExceptionPropagation() {
riggedProxy.exceptionThrowingMethod();
}
@Test(expected = GeneralException.class)
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
public void testExceptionReturningMethod() {
riggedProxy.notReallyExceptionReturningMethod();
}
@Test
public void testActuallyExceptionReturningMethod() {
SpecialException returnedException = riggedProxy.actuallyExceptionReturningMethod();
assertNotNull(returnedException);
}
@Test
public void testWrongRemoteInvocationArgument() {
MessageConverter messageConverter = this.serviceExporter.getMessageConverter();
this.serviceExporter.setMessageConverter(new SimpleMessageConverter() {
private final AtomicBoolean invoked = new AtomicBoolean();
@Override
protected Message createMessage(Object object, MessageProperties messageProperties)
throws MessageConversionException {
Message message = super.createMessage(object, messageProperties);
if (!invoked.getAndSet(true)) {
messageProperties.setContentType(null);
}
return message;
}
});
try {
riggedProxy.simpleStringReturningTestMethod("Test");
}
catch (Exception e) {
assertThat(e, instanceOf(IllegalArgumentException.class));
assertThat(e.getMessage(), containsString("The message does not contain a RemoteInvocation payload"));
}
this.serviceExporter.setMessageConverter(messageConverter);
}
}