lunes, 31 de marzo de 2014

...JUnit in SwitchYard

I'm going to talk about JUnit in SwitchYard, because I have found there is little documentation on the subject. First I will introduce the core concepts of SwitchYard's capabilities to do unit testing (this is taken from the docs, so skip if you already know), and then I will post some tips on typical use cases for creating JUnit tests. I hope you like it.

Concepts

SwitchYardRunner

In order to take advantage of the test support in SwitchYard, ensure that your unit test is annotated with the SwitchYardRunner JUnit test Runner class. The SwitchYardRunner creates and starts an embedded runtime for each test method. After the embedded runtime starts, the project containing the test is packaged as a SwitchYard application and deployed to it. An instance of the SwitchYardTestKit class is injected into the test when a property of type SwitchYardTestKit is declared in the test. This instance represents the runtime state of the deployed SwitchYard test application.
@RunWith(SwitchYardRunner.class)
public class MyServiceTest  {

    private SwitchYardTestKit testKit;

    @Test
    public void testOperation() {
        MyTestServiceHandler service = new MyTestServiceHandler();

        // register the service...
        testKit.registerInOutService("MyService", service);

        // invoke the service and capture the response...
        Message response = newInvoker("MyService")
        .sendInOut("<create>A1234</create>");

        // test the response content by doing an XML comparison with a
        // file resource on the classpath...
        testKit.compareXMLToResource(response.getContent(String.class), "/myservice/expected-create-response.xml");
    }

    private class MyTestServiceHandler implements ExchangeHandler {
        // implement methods....
    }
}
The SwitchYardTestKit class provides a set of utility methods for performing all sorts of deployment configuration and test operations.

SwitchYardTestCaseConfig

The SwitchYardTestCaseConfig annotation is optional. You can use it control the behavior of the SwitchYardRunner:
config
Enables you to add specific testing tools to your test case. Each TestMixIn is a composition-based method that provides customized testing tools for service implementations, gateway bindings, and transformers. When a TestMixIn is annotated on a test class, the SwitchYardRunner handles all the initialization and cleanup (lifecycle) of the TestMixIn instances. It is also possible to manually create and manage TestMixIn instances within your test class if you are not using the SwitchYardRunner.
mixins
Enables you to add specific testing tools to your test case. Each TestMixIn is a composition-based method that provides customized testing tools for service implementations, gateway bindings, and transformers. When a TestMixIn is annotated on a test class, the SwitchYardRunner handles all the initialization and cleanup (lifecycle) of the TestMixIn instances. It is also possible to manually create and manage TestMixIn instances within your test class if you are not using the SwitchYardRunner.
scanner
Enables you to add classpath scanning as part of the test lifecycle. This adds the same Scanner behavior as the one available with the SwitchYard maven build plugin. However, it allows the scanning to take place as part of the test lifecycle. You may need to add Scanners if you want your test to run inside your IDE. This is because running your test inside your IDE bypasses the whole maven build process, which means the build plugin does not perform any scanning
Here is how you can use the SwitchYardTestCaseConfig annotation:
@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(config = "testconfigs/switchyard-01.xml", mixins = {CDIMixIn.class}, scanners = {BeanSwitchYardScanner.class, TransformSwitchYardScanner.class})
public class MyServiceTest  {

    @Test
    public void testOperation() {
        newInvoker("OrderService")
        .operation("createOrder")
        .sendInOnly("<order><product>AAA</product><quantity>2</quantity></order>");
    }
}

config

Enables you to specify a SwitchYard XML configuration file (switchyard.xml) for the test. The SwitchYardRunner attempts to load the specified configuration from the classpath. If it fails to locate the config on the classpath, it attempts to locate it on the file system (For example, within the project structure).

mixins

The TestMixIn feature allows you to selectively enable additional test functionality based on the capabilities of your application. To include MixIn support in your application, you must include a Maven dependency in your application’s pom.xml:
<dependency>
    <groupId>org.switchyard.components</groupId>
    <artifactId>switchyard-component-test-mixin-name</artifactId>
    <version>release-version</version> <!-- e.g. "1.0" -->
    <scope>test</scope>
</dependency>
  • CDIMixIn (switchyard-component-test-mixin-cdi): boostraps a stand-alone CDI environment, automatically discovers CDI beans, registers bean services, and injects references to SwitchYard services.
  • HTTPMixIn (switchyard-component-test-mixin-http): client methods for testing HTTP-based services.
  • SmooksMixIn (switchyard-component-test-mixin-smooks): stand-alone testing of any Smoooks transformers in your application.
  • HornetQMixIn (switchyard-component-test-mixin-hornetq): bootstraps a stand-alone HornetQ server and provides utility methods to interact with it for testing purpose. It can be also used to interact with remote HornetQ server.
  • JCAMixIn (switchyard-component-test-mixin-jca): bootstraps a embedded IronJacamar JCA container and provides utility methods to interact with it for testing purpose. It has a MockResourceAdapter feature to simulate the SwitchYard application behavior without connecting to the real EIS systems. JCAMixIn has been deprecated. It will be removed from the distribution in the future. JCA testing capabilities also provide wiht a TransactionMixIn.
  • NamingMixIn (switchyard-component-test-mixin-naming): provides access to naming and JNDI services within an application.
  • PropertyMixIn (switchyard-test): provides ability to set test values to properties that are used within the configuration of the application

scanners

Scanners add classpath scanning as part of the test lifecycle. This adds the same Scanner behavior as is available with the SwitchYard maven build plugin, but allows the scanning to take place as part of the test lifecycle. The following Scanners are available:
  • BeanSwitchYardScanner: Scans for CDI Bean Service implementations.
  • TransformSwitchYardScanner: Scans for Transformers.
  • BpmSwitchYardScanner: Scans for @Process, @StartProcess, @SignalEvent and @AbortProcessInstance annotations.
  • RouteScanner: Scans for Camel Routes.
  • RulesSwitchYardScanner: Scans for @Rule annotations.

SwitchYardTestKit

Todo

SwitchYardTestCaseConfig

Todo

Enabling test support

Adding test support to your SwitchYard application is simply a matter of adding a dependency to the switchyard-test module in your application’s pom.xml.
<dependency>
    <groupId>org.switchyard</groupId>
    <artifactId>switchyard-test</artifactId>
    <version>[release-version]</version> <!-- e.g. "1.1.1-p5-redhat-1" -->
    <scope>test</scope>
</dependency>
Note: camel dependency version is 2.10.0.redhat-60024
In addition to a dependency on the core test framework, you might want to take advantage of MixIns in your test classes. Dependency information for each MixIn is listed under the Test MixIns section

Metadata and Support Class Injections

TestKit Injection

Injecting the SwitchYardTestKit instance into the test at runtime is simply a case of declaring a property of that type in the test class.
@RunWith(SwitchYardRunner.class)
public class MyServiceTest  {

    private SwitchYardTestKit testKit;

    // implement test methods...
}
The SwitchYard test framework also injects other test support and metadata classes, which we outline in the following sections.

Deployment Injection

You can inject the deployment instance by declaring a property of the type Deployment.
@RunWith(SwitchYardRunner.class)
public class MyServiceTest  {

    private Deployment deployment;

    // implement test methods...
}

SwitchYardModel Injection

You can inject the SwitchYardModel instance by declaring a property of the type SwitchYardModel.
@RunWith(SwitchYardRunner.class)
public class MyServiceTest  {

    private SwitchYardModel model;

    // implement test methods...
}

ServiceDomain Injection

You can inject the ServiceDomain instance by declaring a property of the type ServiceDomain.
@RunWith(SwitchYardRunner.class)
public class MyServiceTest  {

    private ServiceDomain serviceDomain;

    // implement test methods...
}

TransformerRegistry Injection

You can inject the TransformerRegistry instance by declaring a property of the type TransformerRegistry.
@RunWith(SwitchYardRunner.class)
public class MyServiceTest  {

    private TransformerRegistry transformRegistry;

    // implement test methods...
}

TestMixIn Injection

You can inject the TestMixIn Injection instance by declaring a property of the type TestMixIn Injection.
@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(mixins = {CDIMixIn.class, HTTPMixIn.class})
public class MyServiceTest  {

    private CDIMixIn cdiMixIn;
    private HTTPMixIn httpIn;

    // implement test methods...
}

PropertyMixIn Injection

PropertyMixIn instances are injected like any other TestMixIn type, however you must set any properties you wish to use on the MixIn before deployment in order for them to be useed, To do so, use of the @BeforeDeploy annotation:
@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(mixins = {CDIMixIn.class, PropertyMixIn.class, HTTPMixIn.class})
public class MyServiceTest  {

    private PropertyMixIn propMixIn;
    private HTTPMixIn httpMixIn;

    @BeforeDeploy
    public void setTestProperties() {
        propMixIn.set("soapPort", Integer.valueOf(18002));
    }

    // implement test methods...
}

Invoker Injection

To inject Service Invoker instances, declare properties of the type Invoker and annotate them with @ServiceOperation. (Note the annotation value is a dot-delimited Service Operation name of the form [service-name].[operation-name].)
@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(config = "testconfigs/switchyard-01.xml")
public class MyServiceTest  {

    @ServiceOperation("OrderService.createOrder")
    private Invoker createOrderInvoker;

    @Test
    public void test_createOrder() {
        createOrderInvoker.sendInOnly("<order><product>AAA</product><quantity>2</quantity></order>");
    }
}

Tips

Using harmcrest to assert

Hamcrest is a framework for writing matcher objects allowing match rules to be defined declaratively.
We use Hamcrest’s assertThat construct and the standard set of matchers, both of which we statically import:
import static org.hamcrest. MatcherAssert .assertThat;
import static org.hamcrest. Matchers .*;
Hamcrest comes with a library of useful matchers. Here are some of the most important ones.
  • Core
    • anything: always matches, useful if you don’t care what the object under test is
    • describedAs: decorator to adding custom failure description
    • is: decorator to improve readability
  • Logical
    • allOf: matches if all matchers match, short circuits (like Java &&)
    • anyOf: matches if any matchers match, short circuits (like Java ||)
    • not: matches if the wrapped matcher doesn’t match and vice versa
  • Object
    • equalTo: test object equality using Object.equals
    • hasToString: test Object.toString
    • instanceOf, isCompatibleType: test type
    • notNullValue, nullValue: test for null
    • sameInstance: test object identity
  • Beans
    • hasProperty: test JavaBeans properties
  • Collections
    • array: test an array’s elements against an array of matchers
    • hasEntry, hasKey, hasValue: test a map contains an entry, key or value
    • hasItem, hasItems: test a collection contains elements
    • hasItemInArray: test an array contains an element
  • Number
    • closeTo: test floating point values are close to a given value
    • greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo: test ordering
  • Text
    • equalToIgnoringCase: test string equality ignoring case
    • equalToIgnoringWhiteSpace: test string equality ignoring differences in runs of whitespace
    • containsString, endsWith, startsWith: test string matching

Invoke a component service

In order to invoke a component service, a invoker must be injected for certain ServiceOperation. When injecting a service operation, we must specify it in "[service_name].[operation_name]" notation.
import org.switchyard.test.Invoker;
...

@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(mixins = CDIMixIn.class)
public class ExampleServiceTest {

    @ServiceOperation("ExampleService.submitOperation")
    private Invoker submitOperation;

    @Test
    public void testOK() throws Exception {
        ParamIn testParam = new ParamIn()
            .set...(...);

        ParamOut result = submitOperation
            .sendInOut(testParam)
            .getContent(ParamOut.class);

        Assert....
    }

    @Test
    public void testForFault() throws Exception {
        ParamIn testParam = new ParamIn()
            .set...(...);

        try{
            // This method invocation should throw a fault
            ParamOut result = submitOperation
                .sendInOut(testParam)
                .getContent(ParamOut.class);

            Assert.fail
        } catch (InvocationFaultException ifex){
            Assert.... // Assert for correct type of exception
        }
    }
An invocation to a service operation can throw a InvocationFaultException whenever the method should throw a fault. So catching this exception is similar to validating for the fault being trhown. We will check against original exception, checking the type of the InvocationFaultException:
   ifex.isType(MyOriginalException.class)
Or we can use the provided functionality by JUnit setting the expected exception in the test
   @Test(expected=org.switchyard.test.InvocationFaultException.class)

Use SwitchYardTestKit utility methods to ease testing

TestKit provides with a set of utility methods to ease validations and some common operations that are performed on test classes.
  • Access to underlyings
    • getTestInstance:
    • getActivators:
    • getDeployment:
    • getServiceDomain:
    • createQName:
  • Service manipulation
    • registerInOutService:
    • registerInOnlyService:
    • removeService:
    • replaceService:
  • Invocation
    • newInvoker:
  • Transformations
    • addTransformer:
    • newTransformer:
    • registerTransformer:
  • MixIns
    • getMixIns:
    • getMixIn:
  • Dependencies
    • getRequiredDependencies:
    • getOptionalDependencies:
  • Resources
    • getResourceAsStream:
    • readResourceBytes:
    • readResourceString: Reads a resource (file) form the classpath
    • readResourceDocument:
  • Configruation
    • loadSwitchYardModel:
    • loadConfigModel:
  • XML Comparisson
    • compareXMLToResource: Compares a XML in string format with a XML file in the classpath.
    • compareXMLToString:
  • Tracing
    • traceMessages: enables message tracing for the application under test.

org.switchyard.test.MockHandler

Test for transformations in component service

When we test a component invocation, we can test for the appropiate transformation with additional methods on the invocation, for the input transformation as well as for the output transformation:
    ...

    @ServiceOperation("ExampleService.submitOperation")
    private Invoker serviceOperationInvocation;

    @Test
    public void testForInputTransformation() throws Exception {
        ParamOut result =  serviceOperationInvocation
                           .inputType(QName.valueOf("{urn:com.examaple:service:1.0"}submitOperation))
                           .sendInOut(....)
                           .getContent(ParamOut.class);
        Assert....  // Assert that result is OK, so transformation was OK
    }

    @Test
    public void testForOutputXMLTransformation() throws Exception {
        ParamIn testParam = new ParamIn()
            .set...(...);

        ParamOut result =  serviceOperationInvocation
                           .expectedOutputType(QName.valueOf("{urn:com.examaple:service:1.0"}submitOperationResponse))
                           .sendInOut(testParam)
                           .getContent(Element.class); // Expect Element as transformation is for XML

        XMLAssert....  // Assert that result is what is expected
    }
We can use XMLUnit and XMLAssert from org.custommonkey.xmlunit to ease validations.

Mock a service, component or reference

Sometimes it is useful to mock a component, so it is never invoked for the shake of a test. For this, SwitchYardTestKit provides with the ability of adding, replacing or removing services.
    // replace existing implementation for testing purposes
    testKit.removeService("MyService");
    final MockHandler myService = testKit.registerInOnlyService("MyService");

    .... // Invoke the service under test

    // Assert what has arrived ath the mocked service
    final LinkedBlockingQueue<Exchange> recievedMessages = myService.getMessages();
    assertThat(recievedMessages, is(notNullValue()));

    final Exchange recievedExchange = recievedMessages.iterator().next();
    assertThat(recievedExchange.getMessage().getContent(String.class), is(equalTo(...)));
When we want to assert what has arrived/produced the MockHandler, we can get:
  • getMessages(): This provides with the list of received messages.
  • getFaults(): This provides with the list of prodced faults.
Sometimes service is InOut, so we need to mock a response. There are four options:
  • forwardInToOut()
  • forwardInToFault()
  • replyWithOut(Object)
  • replyWithFault(Object)
    final MockHandler mockHandler = testKit.registerInOutService("MyService");
    mockHandler.forwardInToOut();
We can also instruct the MockHandler to wait for certain message.
  • waitForOkMessage()
  • waitForFaultMessage()
It will wait for 5 seconds (default) unless instructed to wait for a different period with setWaitTimeout(milis)

Mock a service for more than 1 method invocation

There are soma cases where the service we are mocking is being called two times in the context of a single unit test, maybe multiple calls to the same method, or to different methods. For this particular case, we can register an EchangeHandler with the mock, while registering and replacing the original service, that will get the message, and where we will have to put some logic to deal with this scenario.
    testKit.replaceService(qname, new ExchangeHandler() {

        @Override
        public void handleMessage(Exchange arg0) throws HandlerException {
            // Here logic to handle with messages
        }

        @Override
        public void handleFault(Exchange arg0) throws HandlerException {
            // Here logic to handle with faults
        }
    });
If this ExchangeHandler needs to be reused, of course, can be made a named class (not anonymous).

Same method multiple invocations

In this scenario, the ExchangeHandler needs to keep track of which invocation number it was in case has to answer with different messages
    testKit.replaceService(qname, new ExchangeHandler() {
        int call=1;

        @Override
        public void handleMessage(Exchange exchange) throws HandlerException {
            if (call++ == 1){ // First call
                // Do whatever wants to be done as result of this operation call, and return the expected output
                Result result = ...; / Result is return type for operation store
                exchange.send(exchange.createMessage().setContent(result));
            }else if (call++ == 2){ // Second call
                // Do whatever wants to be done as result of this operation call, and return the expected output
                Result result = ...; / Result is return type for operation store
                exchange.send(exchange.createMessage().setContent(result));
            }else{
                throw new HandlerException("This mock should not be called more than 2 times");
            }
        }

        @Override
        public void handleFault(Exchange exchange) throws HandlerException {
            // Here logic to handle with faults
        }
    });

Different methods

In this scenario, the ExchangeHandler used will have to check for operation name, to know which method is being invoked.
    testKit.replaceService(qname, new ExchangeHandler() {

        @Override
        public void handleMessage(Exchange exchange) throws HandlerException {
            if (exchange.getContract().getProviderOperation().getName().equals("store")){
                // Do whatever wants to be done as result of this operation call, and return the expected output
                Result result = ...; / Result is return type for operation store
                exchange.send(exchange.createMessage().setContent(result));
            }else if (exchange.getContract().getProviderOperation().getName().equals("getId")){
                // Do whatever wants to be done as result of this operation call, and return the expected output
                exchange.send(exchange.createMessage().setContent(1)); // This operation returns a Int
            }else{
                throw new HandlerException("No operation with that name should be executed");
            }
        }

        @Override
        public void handleFault(Exchange exchange) throws HandlerException {
            // Here logic to handle with faults
        }
    });

How to add credentials before invoking a Service

TODO: Comment this
    protected SecurityContextManager securityMgr;

    @Before
    public void onCreate() {
        securityMgr = new SecurityContextManager(testKit.getServiceDomain());
    }

    ...
    service.operation("deleteEnterprises").sendInOut(addCredentials(message))
                .getContent(DeleteEnterpriseResponse.class);
    ...

    @SuppressWarnings("unchecked")
    private <T> T addCredentials(T request) {
        AuthenticationWrapper wrapper = new AuthenticationWrapper();
        testKit.registerInOutService("AuthenticationWrapper", wrapper);
        QName serviceName = new QName(ObjectFactory.NAME_SPACE, "AuthenticationWrapper");
        Invoker service = new Invoker(testKit.getServiceDomain(), serviceName);
        return (T) service.operation("").sendInOut(request).getContent();
    }

    private class AuthenticationWrapper implements ExchangeHandler {

       @Override
        public void handleMessage(Exchange exchange) throws HandlerException {
            Set<Credential> credentials = new HashSet<Credential>();
            credentials.add(new NameCredential(USERNAME));
            securityMgr.addCredentials(exchange, credentials);
            exchange.send(exchange.getMessage().copy());
        }

        @Override
        public void handleFault(Exchange exchange) {
        }
    }

Invoke a remote service

When a service is published with an SCA binding, we can invoke it remotely with a Remote Invoker.
    public static void main(final String[] ignored) throws Exception {
        // Create a new remote client invoker
        RemoteInvoker invoker = new HttpInvoker("http://localhost:8080/switchyard-remote");

        // Create request payload
        ParamIn input = ...;

        // Create the request message
        RemoteMessage message = new RemoteMessage();
        message.setService(new QName(
            "urn:com.example:1.0","MyService"))
            .setOperation("myOperation").setContent(input);

        // Invoke the service
        RemoteMessage reply = invoker.invoke(message);
        if (reply.isFault()) {
            ...
        } else {
            ParamOut output = (ParamOut)reply.getContent();
            ...
        }
    }

Set properties for a test

Property Test Mix-In for setting test properties that will be respected in configurations.
   private PropertyMixIn pmi;

   ...
   pmi.set("test.property.name", "test");
   pmi.set("test.property.name", Integer.valueOf(100));
   ...
   pmi.get("test.property.name");
   ...

Testing a deployed service with HTTPMixin

Whenever we want to test a deployed service, we can use HTTPMixin to create all the required wishtles.
@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(
        scanners = TransformSwitchYardScanner.class,
        mixins = {CDIMixIn.class, HTTPMixIn.class})
public class WebServiceTest {

    private HTTPMixIn httpMixIn;

    @Test
    public void invokeWebService() throws Exception {
        // Use the HttpMixIn to invoke the SOAP binding endpoint with a SOAP input (from the test classpath)
        // and compare the SOAP response to a SOAP response resource (from the test classpath)...
        httpMixIn.setContentType("application/soap+xml");
        httpMixIn.postResourceAndTestXML("http://localhost:18001/service-context/ServiceName", "/xml/soap-request.xml", "/xml/soap-response.xml");
    }
}
Or from a main class:
    /**
     * Only execution point for this application.
     * @param ignored not used.
     * @throws Exception if something goes wrong.
     */
    public static void main(final String[] ignored) throws Exception {

        HTTPMixIn soapMixIn = new HTTPMixIn();
        soapMixIn.initialize();

        try {
            String result = soapMixIn.postFile(URL, XML);
            System.out.println("SOAP Reply:\n" + result);
        } finally {
            soapMixIn.uninitialize();
        }
    }

Creating an Embedded WebService to test a component

In some situations we only want to test a component, so we decide to expose it dynamically as a WebService an invoke it.
import javax.xml.ws.Endpoint;
...

@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(
        config = SwitchYardTestCaseConfig.SWITCHYARD_XML,
        scanners = {TransformSwitchYardScanner.class},
        mixins = {HTTPMixIn.class})
public class CamelSOAPProxyTest {

    private static final String WEB_SERVICE = "http://localhost:8081/MyService";

    private HTTPMixIn _http;
    private Endpoint _endpoint;

    @BeforeDeploy
    public void setProperties() {
        System.setProperty("org.switchyard.component.http.standalone.port", "8081");
    }

    @Before
    public void startWebService() throws Exception {
        _endpoint = Endpoint.publish(WEB_SERVICE, new ReverseService());
    }

    @After
    public void stopWebService() throws Exception {
        _endpoint.stop();
    }

    @Test
    public void testWebService() throws Exception {
        _http.postResourceAndTestXML(WEB_SERVICE, "/xml/soap-request.xml", "/xml/soap-response.xml");
    }
}

Testing a deployed service with HornetQMixIn

Sometimes we need to test an application that has a JMS binding and we want to test with the binding itself. For these use cases, HornetQMixIn comes to the rescue.
HornetQMixIn gets its configuration from 2 files that has to be on the classpath for the test:
hornetq-configuration.xml: Contains the configuration for the HornetQ server.
 <configuration xmlns="urn:hornetq">

        <paging-directory>target/data/paging</paging-directory>
        <bindings-directory>target/data/bindings</bindings-directory>
        <persistence-enabled>false</persistence-enabled>
        <journal-directory>target/data/journal</journal-directory>
        <journal-min-files>10</journal-min-files>
        <large-messages-directory>target/data/large-messages</large-messages-directory>
        <security-enabled>false</security-enabled>

        <connectors>
                <connector name="invm-connector">
                        <factory-class>org.hornetq.core.remoting.impl.invm.InVMConnectorFactory</factory-class>
                </connector>
                <connector name="netty-connector">
                 <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
                 <param key="port" value="5545"/>
      </connector>
        </connectors>

        <acceptors>
                <acceptor name="invm-acceptor">
                        <factory-class>org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory</factory-class>
                </acceptor>
                <acceptor name="netty-acceptor">
                        <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
                        <param key="port" value="5545"/>
                </acceptor>
        </acceptors>

</configuration>
hornetq-jms.xml: Contains the definition of the connection factories, queues, topics,…
<configuration xmlns="urn:hornetq">

   <connection-factory name="ConnectionFactory">
      <connectors>
        <connector-ref connector-name="invm-connector"/>
      </connectors>

      <entries>
         <entry name="ConnectionFactory"/>
      </entries>
   </connection-factory>

   <queue name="TestRequestQueue">
      <entry name="TestRequestQueue"/>
   </queue>
   <queue name="TestReplyQueue">
      <entry name="TestReplyQueue"/>
   </queue>

</configuration>
To use it in test, you only need to get a reference to the MixIn and use the appropiate mixin methods:
@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(
        config = SwitchYardTestCaseConfig.SWITCHYARD_XML,
        mixins = {CDIMixIn.class, HornetQMixIn.class}
)

public class JmsBindingTest {

    private HornetQMixIn _hqMixIn;


    @Test
    public void testHelloService() throws Exception {
        Session session = _hqMixIn.getJMSSession();
        MessageProducer producer = session.createProducer(HornetQMixIn.getJMSQueue(REQUEST_NAME));
        Message message = _hqMixIn.createJMSMessage(createPayload(NAME));
        producer.send(message);

        MessageConsumer consumer = session.createConsumer(HornetQMixIn.getJMSQueue(REPLY_NAME));
        message = consumer.receive(3000);
        String reply = _hqMixIn.readStringFromJMSMessage(message);
        SwitchYardTestKit.compareXMLToString(reply, createExpectedReply(NAME));
    }

    @Before
    public void getHornetQMixIn() {
        _hqMixIn = _testKit.getMixIn(HornetQMixIn.class);
    }
Or testing from a standalone client:
   public static void main(final String[] args) throws Exception {

        HornetQMixIn hqMixIn = new HornetQMixIn(false)
                                    .setUser(USER)
                                    .setPassword(PASSWD);
        hqMixIn.initialize();

        try {
            Session session = hqMixIn.getJMSSession();
            final MessageProducer producer = session.createProducer(HornetQMixIn.getJMSQueue(REQUEST_NAME));
            producer.send(hqMixIn.createJMSMessage("<....>");
            System.out.println("Message sent. Waiting for reply ...");

            final MessageConsumer consumer = session.createConsumer(HornetQMixIn.getJMSQueue(REPLY_NAME));
            Message message = consumer.receive(3000);
            String reply = hqMixIn.readStringFromJMSMessage(message);
            System.out.println("REPLY: \n" + reply);
        } finally {
            hqMixIn.uninitialize();
        }

    }

Testing a deployed service with TransactionMixIn

To test your required services with a transaction, we can use TransactionMixIn. TransactionMixIn with combination of CDIMixIn will inject a UserTransaction object when required. If you need explicit access, you can @Inject the UserTransaction object, but if not, it will be injected in SwitchYard’s functionalities for you under the covers. This MixIn introduces NamingMixIn for you, as it is a required dependency.
@SwitchYardTestCaseConfig(
    config = SwitchYardTestCaseConfig.SWITCHYARD_XML,
    mixins = {CDIMixIn.class, TransactionMixIn.class}
)
public YourClass{
    ....
}
And it will bind following objects into the JNDI tree:
  • TransactionManager: "java:jboss/TransactionManager"
  • UserTransaction: "java:jboss/UserTransaction"
  • TransactionSynchronizationRegistry: "java:jboss/TransactionSynchronizationRegistry"
If you need access to the provided objects, you can use the MixIn to get a reference:
    private TransactionMixIn transaction;
    ....
    transaction.getUserTransaction();
    transaction.getTransactionManager();
    transaction.getSynchronizationRegistry();
This mixin will leave transactional logs in "target/tx-store".
This mixin uses Arjuna Transactions Provider (com.arjuna.ats.jta).

Testing JPA functionality

TODO: See: ./quickstarts/camel-jpa-binding/src/test/java/org/switchyard/quickstarts/camel/jpa/binding/CamelJpaBindingTest.java

Testing in a container with Arquillian

TODO:

Testing with a different (reduced) Switchyard configuration file

Use this annotation on the test class:
@SwitchYardTestCaseConfig(config = "switchyard-XXXXX.xml", mixins = {.....})
And create your reduced switchyard-XXXX.xml within the test/resources folder at the same package level as your test class.

Selectively enabling activators for a Test

The test framework defaults to a mode where the entire application descriptor is processed during a test run. This means all gateway bindings and service implementations are activated during each test. There are times when this may not be appropriate, so we allow activators to be selectively enabled or disabled based on your test configuration. In this example, SOAP bindings are excluded from all tests. (This means that SOAP gateway bindings will not be activated when the test framework loads the application.)
@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(config = "testconfigs/switchyard-01.xml" exclude="soap")
public class NoSOAPTest  {
   ...
}
This example includes only CDI bean services as defined in the application descriptor:
@RunWith(SwitchYardRunner.class)
@SwitchYardTestCaseConfig(config = "testconfigs/switchyard-02.xml" include="bean")
public class BeanServicesOnlyTest  {
...
}
Sometimes you will need to add some procedures before you perform the test. The JUnit @Before operation is invoked imediately after the application is deployed. You cannot, however, use it if you expect something to happen before deployment.

Preparing procedure for test

Preparing procedure for the Test Sometimes we need to add some procedures before test is performed. JUnit @Before operation is invoked right after the application is deployed, however, it can’t be used if you expect something before deploy. We have @BeforeDeploy annotation for this purpose.

martes, 11 de marzo de 2014

...customize SOAP Fault in SwitchYard

Sometimes it may be necessary to customize the returned Fault to the client, to be consistent with the specification/contract you have for your service.
By default, SwitchYard may wrap every exception/Fault occurred in the engine (Bus, Pipeline, Handlers,...) with a SOAPFault maybe containing a SwitchYardException.

As faultcode may be customize by any service contract, or the Fault Actor:
"Applications that do not act as the ultimate destination of the SOAP message MUST include the faultactor element in a SOAP Fault element. The ultimate destination of a message MAY use the faultactor element to indicate explicitly that it generated the fault", or any other part of the SoapFault.

To do this, there might be many possibilities, but one that I have proved to work is, creating a Custom MessageComposer, to handle this.

I will show a very basic example to demonstrate how to do this.

I have done an example service that returns a DownloaderException when timeout is less than 0, as you can see in the picture below.




1. Create your Custom MessageComposer. You can extend SOAPMessageComposer to use all of it's functionality. This class is not intended for subclassing, so depending on the needs, there may be a need to overwrite a lot of stuff. For this case in particular, there is no need.
public class CustomFaultMessageComposer extends SOAPMessageComposer {

 @Override
 public SOAPBindingData decompose(Exchange exchange, SOAPBindingData target)
   throws Exception {
  SOAPBindingData data = target;
  try{
   data = super.decompose(exchange, target);
  }catch(Exception e){
   data.getSOAPMessage().getSOAPBody().addFault(new QName("100"), "ERROR in transformation");
  }
        try {
            getContextMapper().mapTo(exchange.getContext(), data);
        } catch (Exception ex) {
            throw SOAPMessages.MESSAGES.failedToMapContextPropertiesToSOAPMessage(ex);
        }
  
        return data;  
 }
}

2. Add your Custom MessageComposer to the binding:
    <sca:service name="MyServicePortType" promote="MyServiceBean/MyService">
      <sca:interface .wsdl="" interface="MyService.wsdl#wsdl.porttype(MyServicePortType)">
      <soap:binding .soap="" name="soap1">
        <soap:messagecomposer class="com.example.switchyard.soap.CustomFaultMessageComposer" unwrapped="true">
        ...
      </soap:messagecomposer></soap:binding>
    </sca:interface>

3. Deploy your application and make it throw an Exception.



Probably there are more things to check for, as MessageComposers are applied in InboundHandlers, there may be exceptions/errors that happen outside the scope of what can be controlled by the MessageComposers and may need to be controlled in some other place, like a CXF Interceptor. But I haven't been able to make it work there.

I hope this is handy for anybody.

This post is inspired by a discussion in SwitchYard forum.

Grab the code

viernes, 7 de marzo de 2014

...regarding unwrapped in SwitchYard SOAP bindings

Hi again,
I've been playing a while with SwitchYard and the SOAP binding, for Web Services kind of services, where one would do the Components with java,camel,whatever and make them accessible through a Java interface. Then one could probably promote the component service, as a composite service, and then publish it with a WSDL interface.
For that to work, you need to transform from you SOAP messages to Java beans or basic types. You have a bunch of options for which JAXB is the easiest one, for this kind of transformations, just annotate your beans, and you should be ready.

Your beans, need to be annotated with @XMLRootElement and have an ObjectFactory class that will provide for the required transformations between XML and Java and back.

These annotated beans and ObjectFactory class can be generated with wsconsume script located in the bin folder of the AS. Just run the script against your wsdl and keep the sources.

One thing that nobody may know is that for SwitchYard it is easier to work with unwrapped messages so, there is an option, when creating/configuring the SOAP binding that says "Unwrapped payload", as can be seen here:
What this means is that it will remove the wrapper part of the message, which usually translates to the operation for you.
If you have this original message:

  1. <soap:Body>  
  2.         <orders:submitOrder xmlns:orders="urn:switchyard-quickstart:bean-service:1.0">  
  3.             <order>  
  4.                 <orderId>PO-19838-XYZ</orderId>  
  5.                 <itemId>BUTTER</itemId>  
  6.                 <quantity>200</quantity>  
  7.             </order>  
  8.         </orders:submitOrder>  
  9. </soap:Body>  

The message you will need to handle in the transformation will be:

  1. <order xmlns:orders="urn:switchyard-quickstart:bean-service:1.0">  
  2.                 <orderId>PO-19838-XYZ</orderId>  
  3.                 <itemId>BUTTER</itemId>  
  4.                 <quantity>200</quantity>  
  5. </order>  


So beware of this functionality, and understand how it works.


There is a comment in the code, that reads:

if (unwrapped){ ...// peel off the operation wrapper, if present ...}

...SwitchYard concepts and terms

Hi,
For a some time right now, I'm up to learn Red Hat's new SOA platform, that is called Fuse Service Works. There is not much information about this product and it's internals, so I have decided to start publishing information about it as I learn myself my way.
In this post, I'm talking about SwitchYard concepts and terms.

SwitchYard is the execution engine of the SOA platform. It is based on SCA, and you can find documentation about it, although on a basic stage, at SwitchYard official documentation

There are some basic concepts that need to be understood from the internals of SwitchYard. These are the main classes that are in there.

org.switchyard.Exchange: An Exchange represents an instance of a service invocation with a specific message exchange pattern (e.g. InOnly, InOut).  Exchange provides a conduit for the messages that flow into and out of a service  as part of a service invocation.  Unlike messages, an exchange cannot be copied and reused across service invocations.  State associated with  an invocation (i.e. context) is maintained at the exchange level.

org.switchyard.Message: A Message represents an individual input or output of a service, the content of which is interpreted by service implementation logic.  A Message does not carry context specific to a service invocation, which means that it can be copied and reused across service invocations. There are two distinct parts to a message:

  • Content: the main body, or payload, of the message. There is only one body per message instance. The message body is mutable, so message processing logic can access the content, change it (transform, enrich, etc.), and then set it back on the message.
  • Attachments: provide the ability to associate content with a message separate from  the main body, allowing it to be parsed independently. One example  would be a binary image that is referenced by the main body of the message.  The attachment may be too large to be processed in certain services or the service implementation may not be able to  parse/interpret it.


org.switchyard.Context: Holds contextual information around the exchange of messages between a service consumer and provider.

org.switchyard.Service: A service registered with the SwitchYard runtime.

org.switchyard.ServiceReference: A service registered with the SwitchYard runtime.

org.switchyard.ServiceDomain: A ServiceDomain represents a collection of services with a shared set of resources, configuration, and policy definitions.  The ServiceDomain interface is used by software components to provide and/or consume services.  These software components include protocol gateways, service containers, translation engines, adapters, orchestration and routing engines.

org.switchyard.ExchangeState: Represents the state of an Exchange (OK, FAULT)

org.switchyard.ExchangePhase: Represents the phase of an exchange. (INPUT or OUTPUT)

org.switchyard.ExchangeHandler: The role of a Handler is to handle messages and fault events during the course of a service invocation.  When consuming a service, a handler can be registered during Exchange creation to handle consumer events (e.g. fault or reply message).  When providing a service, a handler is specified while registering the service to process invocations of that service.

org.switchyard.ExchangePattern: The list of supported exchange patterns within SwitchYard. (IN_ONLY, IN_OUT)

org.switchyard.metadata.ExchangeContract: Two-way Exchange contract, detailing the requirements of both the consumer and provider ServiceOperation being invoked.

org.switchyard.metadata.ServiceOperation: Representation of an operation on a ServiceInterface. Each operation has:

  •  an exchange pattern (IN_OUT, IN_ONLY)
  •  a name
  •  an input message referenced type
  •  an (optional) output message type
  •  an (optional) fault message type

The mapping of operation and message names is defined by the concrete implementation of ServiceInterface.  For example, the expected mapping of a Java interface would be Java method name to ServiceInterface operation name.

org.switchyard.metadata.ServiceInterface: The canonical representation of a service interface in SwitchYard.  Every service in SwitchYard is registered with exactly one ServiceInterface, providing information on the type, operations, and input/output messages for the service. The SwitchYard runtime provides concrete implementations of ServiceInterface for Java and WSDL interface types. There is also a default type of *ServiceInterface.DEFAULT_TYPE* which is used to represent services which do not publish a formal contract.

org.switchyard.ServiceMetadata:  Contains runtime details on services and service references registered in SwitchYard.  Instances of ServiceMetadata can be created and updated using the ServiceMetadataBuilder class

There are some more, and I'll try to update this post, as a reference as I get more info.

Graphically, these classes and their relations can be seen here (click to see a larger picture):
SwitchYard core classes
SwitchYard core classes