/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.core.mule.model;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mule.runtime.api.message.Message.of;
import static org.mule.runtime.core.api.Event.getCurrentEvent;
import static org.mule.runtime.core.api.Event.setCurrentEvent;
import static org.mule.tck.MuleTestUtils.getTestFlow;
import org.mule.runtime.api.exception.MuleException;
import org.mule.runtime.core.DefaultEventContext;
import org.mule.runtime.core.DefaultMuleEventContext;
import org.mule.runtime.core.api.Event;
import org.mule.runtime.core.api.MuleEventContext;
import org.mule.runtime.core.api.config.MuleProperties;
import org.mule.runtime.core.api.construct.FlowConstruct;
import org.mule.runtime.core.api.model.EntryPointResolverSet;
import org.mule.runtime.core.api.model.resolvers.ArrayEntryPointResolver;
import org.mule.runtime.core.api.model.resolvers.EntryPointNotFoundException;
import org.mule.runtime.core.api.model.resolvers.LegacyEntryPointResolverSet;
import org.mule.runtime.core.internal.message.InternalMessage;
import org.mule.tck.MuleTestUtils;
import org.mule.tck.junit4.AbstractMuleContextTestCase;
import org.mule.tck.testmodels.fruit.Apple;
import org.mule.tck.testmodels.fruit.Banana;
import org.mule.tck.testmodels.fruit.Fruit;
import org.mule.tck.testmodels.fruit.FruitBowl;
import org.mule.tck.testmodels.fruit.FruitCleaner;
import org.mule.tck.testmodels.fruit.FruitLover;
import org.mule.tck.testmodels.fruit.Kiwi;
import org.mule.tck.testmodels.fruit.Orange;
import org.mule.tck.testmodels.fruit.WaterMelon;
import java.util.Arrays;
import org.junit.Test;
public class LegacyEntryPointResolverTestCase extends AbstractMuleContextTestCase {
/** Name of the method override property on the event. */
private static final String METHOD_PROPERTY_NAME = MuleProperties.MULE_METHOD_PROPERTY;
/** Name of the non-existent method. */
private static final String INVALID_METHOD_NAME = "nosuchmethod";
@Test
public void testExplicitMethodMatch() throws Exception {
try {
LegacyEntryPointResolverSet resolver = new LegacyEntryPointResolverSet();
FlowConstruct flowConstruct = getTestFlow(muleContext);
final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of("blah"))
.build();
MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, event);
resolver.invoke(new WaterMelon(), eventContext, Event.builder(eventContext.getEvent()));
} catch (MuleException e) {
fail("Test should have passed: " + e);
}
}
@Test
public void testExplicitMethodMatchComplexObject() throws Exception {
try {
LegacyEntryPointResolverSet resolver = new LegacyEntryPointResolverSet();
FlowConstruct flowConstruct = getTestFlow(muleContext);
final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(new FruitLover("Mmmm")))
.build();
MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, event);
resolver.invoke(new FruitBowl(), eventContext, Event.builder(eventContext.getEvent()));
} catch (MuleException e) {
fail("Test should have passed: " + e);
}
}
@Test
public void testExplicitMethodMatchSetArrayFail() throws Exception {
try {
LegacyEntryPointResolverSet resolver = new LegacyEntryPointResolverSet();
FlowConstruct flowConstruct = getTestFlow(muleContext);
final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(new Fruit[] {new Apple(), new Orange()}))
.build();
MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, event);
resolver.invoke(new FruitBowl(), eventContext, Event.builder(eventContext.getEvent()));
fail("Test should have failed because the arguments were not wrapped properly: ");
} catch (MuleException e) {
// expected
}
}
@Test
public void testExplicitMethodMatchSetArrayPass() throws Exception {
try {
LegacyEntryPointResolverSet resolver = new LegacyEntryPointResolverSet();
FlowConstruct flowConstruct = getTestFlow(muleContext);
final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(new Object[] {new Fruit[] {new Apple(), new Orange()}}))
.build();
MuleEventContext eventContext =
new DefaultMuleEventContext(flowConstruct, event);
resolver.invoke(new FruitBowl(), eventContext, Event.builder(eventContext.getEvent()));
} catch (MuleException e) {
fail("Test should have passed: " + e);
}
}
/*
* this tests the same as above except it uses the {@link ArrayEntryPointResolver} and does not wrap the args with an array
*/
@Test
public void testExplicitMethodMatchSetArrayPassUsingExplicitResolver() throws Exception {
try {
LegacyEntryPointResolverSet resolver = new LegacyEntryPointResolverSet();
resolver.addEntryPointResolver(new ArrayEntryPointResolver());
FlowConstruct flowConstruct = getTestFlow(muleContext);
final Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(new Fruit[] {new Apple(), new Orange()}))
.build();
MuleEventContext eventContext = new DefaultMuleEventContext(flowConstruct, event);
resolver.invoke(new FruitBowl(), eventContext, Event.builder(eventContext.getEvent()));
} catch (MuleException e) {
fail("Test should have passed: " + e);
}
}
/**
* Tests entrypoint discovery when there is more than one discoverable method with MuleEventContext parameter.
*/
@Test
public void testFailEntryPointMultiplePayloadMatches() throws Exception {
EntryPointResolverSet resolverSet = new LegacyEntryPointResolverSet();
try {
FlowConstruct flowConstruct = MuleTestUtils.getTestFlow(muleContext);
setCurrentEvent(Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of("Hello"))
.build());
MuleEventContext eventContext = new DefaultMuleEventContext(getTestFlow(muleContext), getCurrentEvent());
resolverSet.invoke(new MultiplePayloadsTestObject(), eventContext, Event.builder(getCurrentEvent()));
fail("Should have failed to find entrypoint.");
} catch (EntryPointNotFoundException itex) {
// expected
}
}
/**
* If there was a method parameter specified to override the discovery mechanism and no such method exists, an exception should
* be thrown, and no fallback to the default discovery should take place.
*/
@Test
public void testMethodOverrideDoesNotFallback() throws Exception {
EntryPointResolverSet resolverSet = new LegacyEntryPointResolverSet();
FlowConstruct flowConstruct = MuleTestUtils.getTestFlow(muleContext);
setCurrentEvent(Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(new FruitLover("Yummy!")))
.build());
// those are usually set on the endpoint and copied over to the message
final String methodName = "nosuchmethod";
final String propertyName = MuleProperties.MULE_METHOD_PROPERTY;
Event event = getCurrentEvent();
event = Event.builder(event)
.message(InternalMessage.builder(event.getMessage()).addOutboundProperty(propertyName, methodName).build()).build();
MuleEventContext eventContext = new DefaultMuleEventContext(getTestFlow(muleContext), event);
resolverSet.invoke(new FruitBowl(), eventContext, Event.builder(event));
// fail("Should have failed to find an entrypoint.");
}
/**
* If there was a method parameter specified to override the discovery mechanism and a Callable instance is serving the request,
* call the Callable, ignore the method override parameter.
*/
@Test
public void testMethodOverrideIgnoredWithCallable() throws Exception {
EntryPointResolverSet resolver = new LegacyEntryPointResolverSet();
FlowConstruct flowConstruct = MuleTestUtils.getTestFlow(muleContext);
setCurrentEvent(Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(new FruitLover("Yummy!")))
.build());
// those are usually set on the endpoint and copied over to the message
Event event = getCurrentEvent();
event = Event.builder(event)
.message(InternalMessage.builder(event.getMessage()).addOutboundProperty(METHOD_PROPERTY_NAME, INVALID_METHOD_NAME)
.build())
.build();
Apple apple = new Apple();
apple.setAppleCleaner(new FruitCleaner() {
@Override
public void wash(Fruit fruit) {
// dummy
}
@Override
public void polish(Fruit fruit) {
// dummy
}
});
apple.setMuleContext(muleContext);
MuleEventContext eventContext = new DefaultMuleEventContext(getTestFlow(muleContext), event);
resolver.invoke(apple, eventContext, Event.builder(event));
}
/**
* If there was a method parameter specified to override the discovery mechanism and a target instance has a method accepting
* MuleEventContext, proceed to call this method, ignore the method override parameter.
*/
@Test
public void testMethodOverrideIgnoredWithEventContext() throws Exception {
EntryPointResolverSet resolverSet = new LegacyEntryPointResolverSet();
FlowConstruct flowConstruct = MuleTestUtils.getTestFlow(muleContext);
setCurrentEvent(Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(new FruitLover("Yummy!")))
.build());
// those are usually set on the endpoint and copied over to the message
final String methodName = "nosuchmethod";
final String propertyName = MuleProperties.MULE_METHOD_PROPERTY;
Event event = getCurrentEvent();
event = Event.builder(event)
.message(InternalMessage.builder(event.getMessage()).addOutboundProperty(propertyName, methodName).build()).build();
try {
MuleEventContext eventContext = new DefaultMuleEventContext(getTestFlow(muleContext), event);
resolverSet.invoke(new Kiwi(), eventContext, Event.builder(event));
fail("no such method on service");
} catch (EntryPointNotFoundException e) {
// expected
}
}
/** Test for proper resolution of a method that takes an array as argument. */
// TODO MULE-1088: currently fails, therefore disabled
@Test
public void testArrayArgumentResolution() throws Exception {
EntryPointResolverSet resolverSet = new LegacyEntryPointResolverSet();
Object payload = new Object[] {new Fruit[] {new Apple(), new Banana()}};
FlowConstruct flowConstruct = MuleTestUtils.getTestFlow(muleContext);
Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(payload)).build();
setCurrentEvent(event);
FruitBowl bowl = new FruitBowl();
assertFalse(bowl.hasApple());
assertFalse(bowl.hasBanana());
MuleEventContext eventContext = new DefaultMuleEventContext(getTestFlow(muleContext), event);
resolverSet.invoke(bowl, eventContext, Event.builder(event));
assertTrue(bowl.hasApple());
assertTrue(bowl.hasBanana());
}
/** Test for proper resolution of a method that takes a List as argument. */
@Test
public void testListArgumentResolution() throws Exception {
EntryPointResolverSet resolverSet = new LegacyEntryPointResolverSet();
Object payload = Arrays.asList(new Fruit[] {new Apple(), new Banana()});
FlowConstruct flowConstruct = MuleTestUtils.getTestFlow(muleContext);
Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(payload))
.build();
setCurrentEvent(event);
FruitBowl bowl = new FruitBowl();
assertFalse(bowl.hasApple());
assertFalse(bowl.hasBanana());
MuleEventContext eventContext = new DefaultMuleEventContext(getTestFlow(muleContext), event);
resolverSet.invoke(bowl, eventContext, Event.builder(event));
assertTrue(bowl.hasApple());
assertTrue(bowl.hasBanana());
}
/** Test for proper resolution of an existing method specified as override */
@Test
public void testExplicitOverride() throws Exception {
EntryPointResolverSet resolverSet = new LegacyEntryPointResolverSet();
Object payload = Arrays.asList(new Fruit[] {new Apple(), new Banana()});
FlowConstruct flowConstruct = MuleTestUtils.getTestFlow(muleContext);
Event event = Event.builder(DefaultEventContext.create(flowConstruct, TEST_CONNECTOR_LOCATION))
.message(of(payload))
.build();
setCurrentEvent(event);
final String methodName = "setFruit";
final String propertyName = MuleProperties.MULE_METHOD_PROPERTY;
event = Event.builder(event)
.message(InternalMessage.builder(event.getMessage()).addOutboundProperty(propertyName, methodName).build()).build();
FruitBowl bowl = new FruitBowl();
assertFalse(bowl.hasApple());
assertFalse(bowl.hasBanana());
MuleEventContext eventContext = new DefaultMuleEventContext(getTestFlow(muleContext), event);
resolverSet.invoke(bowl, eventContext, Event.builder(event));
assertTrue(bowl.hasApple());
assertTrue(bowl.hasBanana());
}
}