SwitchYard tutorial

switchyard tutorialIn this tutorial we will describe how to create your first SwitchYard Service. We will then show how to consume it through a JSF interface or a SOAP based client.

 

SwitchYard is a lightweight service delivery framework which provides support for developing, deploying and managing service oriented applications. You can download SwitchYard from JBoss site

Once unzipped, you will see that the distribution contains a bundled JBoss AS 7 where you can deploy your services.

There are several service implementations available in SwitchYard which allow routing services between SwitchYard and other frameworks. You might for example connect your SwitchYard services to Apache Camel services or Drools decision rules.

 

In this tutorial we will show how to use Bean services which leverages the power of Java EE6 and CDI allowing to turn Java objects into services by means of a simple @Service annotation added to your bean. Then, your beans are automatically registered as Services and can be injected as CDI beans using @Inject.
In order to do that, you need to use a pluggable container named the Bean Component which allows Java classes (or beans) to provide and consume services. The bean component has been implemented as a Weld extension, thus you don't need to learn a new programming model: Bean Services are standard CDI beans with a few extra annotations.

In this example, the MathService interface represents the Service Interface, defining the service operations that are implemented by the MathServiceBean class: this can be done through the org.switchyard.component.bean.Service annotation:

package com.sample;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

import org.switchyard.component.bean.Reference;
import org.switchyard.component.bean.Service;

@Service(MathService.class)
@ApplicationScoped
public class MathServiceBean implements MathService {
    
        
    @Override
    public Result addition(Calculator order) {
         
        Result result = new Result();
        result.setTotal(order.getNumber1() + order.getNumber2());
        
        
        return result;
    }

}

package com.sample;

public interface MathService {
    
    Result addition(Calculator order);
    
}

And this is the bean class that wraps the result of the addition (we are using a class instead of a primitive in case you plan to add more complex operations like divisions):
package com.sample;

public class Result {

    private int total;

    public int getTotal() {
        return total;
    }

    public void setTotal(int total) {
        this.total = total;
    }
}

Finally, this is the switchyard.xml configuration file where your Service and its implementation class are described:

<?xml version="1.0" encoding="UTF-8"?>
<switchyard xmlns="urn:switchyard-config:switchyard:1.0" name="orders" targetNamespace="urn:switchyard-quickstart-demo:orders:0.1.0">
    <composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" name="orders" targetNamespace="urn:switchyard-quickstart-demo:orders:0.1.0">
        <service name="MathService" promote="MathService" />

        <component name="MathService">
            <implementation.bean xmlns="urn:switchyard-component-bean:config:1.0" class="com.sample.MathServiceBean"/>
            <service name="MathService">
                <interface.java interface="com.sample.MathService"/>
            </service>
            
        </component>
    </composite>

</switchyard>

The last thing you need adding is an empty META-INF/beans.xml file in your deployed application. When the application is deployed, the Weld runtime scans the application for beans and picks up @Service beans and make them available to the application deployer (will depend on the container). At this point, the service can be invoked from other services within SwitchYard or bound to a wire protocol via SwitchYard gateways.

Testing Services with JSF

The JavaServer Faces (JSF) technology can be used to quickly design your UI of Java EE applications. JSF is very tightly integrated with CDI to provide the Object Model behind the JSF user interface components.

It's possible to annotate your SwitchYard Service CDI beans with the @Named annotation and inject them directly into your application's JSF components; however invoking directly the Service from JSF would result in a tight coupling between the JSF page and the Service.

Thus, you should invoke your SwitchYard CDI Bean Service through the SwitchYard Exchange mechanism by means of the @Reference injected Service reference. This mechanism provides a client side proxy bean that handles all the SwitchYard Exchange invocation.

package com.sample;

import org.switchyard.component.bean.Reference;

import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.Serializable;

@Named
@RequestScoped
public class Calculator implements Serializable {

    @Inject
    @Reference   
    private MathService orderService;

    private int number1;
    private int number2;
    private int total;

    // Getters - Setters omitted for brevity

    public void sum() {
        total = orderService.addition(this).getTotal();

    }
}

And this is the JSF page which invokes the Calculator Named Bean:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
    <!-- CSS omitted for brevity -->
</h:head>
<h:body>
    <h2>Switchyard Simple Calculator</h2>
    <h:form id="jsfexample">
        <h:panelGrid columns="2" styleClass="default">

            <h:outputText value="Enter number 1:" />
            <h:inputText value="#{calculator.number1}" />

            <h:outputText value="Enter number 2:" />
            <h:inputText value="#{calculator.number2}" />

            <h:commandButton actionListener="#{calculator.sum}"
                styleClass="buttons" value="Save key/value" />
            <h:outputText value="Total #{calculator.total}" />                

            <h:messages />

        </h:panelGrid>

    </h:form>
</h:body>
</html>

So here is how your Web application structure should look like:

SwitchYardExample.war

?   home.xhtml
?
????META-INF
?      |  switchyard.xml
?  
?
????WEB-INF
    ?   beans.xml
    ?   faces-config.xml
    ?   web.xml
    ?
    ????classes
        ????com
        ?   ????sample
        ?           Calculator.class
        ?           MathService.class
        ?           MathServiceBean.class
        ?           Result.class

You can deploy your application to built-in JBoss AS 7 server (C:\switchyard-as7-0.4\standalone\deployments) and invoke it (supposing that your Web application name was SwitchYardExample) :

http://localhost:8080/SwitchYardExample/home.xhtml

By filling up the input text, your Calculator bean should proxy your call to your @Service which returns the result:

jboss soa switchyard tutorial web services

Follow us on Twitter