JBoss Community Archive (Read Only)

SwitchYard

Bean

Overview 

The Bean Component is a pluggable container in SwitchYard which allows Java classes (or beans) to provide and consume services. This means that you can implement a service by simply annotating a Java class. It also means you can consume a service by injecting a reference to that service directly into your Java class. Rather than writing our own POJO container to provide this capability, we have implemented the bean component as a Weld extension. No need to learn a new programming model - bean services are standard CDI beans with a few extra annotations. This also opens up the possibilities of how SwitchYard is used; you can now expose existing CDI-based beans in your application as services to the outside world or consume services within your bean

Creating a Bean Service

To create a new Bean service you only need a few pieces of information:

  • Name : the name of the Java class for your bean service.

  • Service Name : the name of the service your bean will provide.

  • Interface : the contract for the service being provided.  Java is the only valid interface type for bean services.

Note that starting with the interface value will default the names for Name and Service Name, which can speed things up if you're in a hurry.

After clicking Finish, you will have a new class that looks something like this:

package com.example.switchyard.docs;

import org.switchyard.component.bean.Service;

@Service(Example.class)
public class ExampleBean implements Example {

}

The @Service annotation allows the SwitchYard CDI Extension to discover your bean at runtime and register it as a service.  The value of the annotation (Example.class in the above example) represents the service contract for the service.  Every bean service must have an @Service annotation with a value identifying the service interface for the service.

To complete the definition of your service, add one or more operations to the service interface and provide a corresponding implementation in your bean:

package com.example.switchyard.docs;

import org.switchyard.component.bean.Service;

@Service(Example.class)
public class ExampleBean implements Example {

   public void greet(Person person) {
       // implement service logic here for greet operation
   }
}

Consuming a Service

In addition to providing a service in SwitchYard, beans can also consume other services.  These services can be provided in the same application by other implementations, or they could be wired to gateway bindings to invoke services over JMS, SOAP, FTP, etc.  The SwitchYard runtime handles the resolution of the service reference to a concrete service, allowing your service logic to remain blissfully ignorant. Invocations made through this reference are routed through the SwitchYard exchange mechanism.

Consuming a SwitchYard service from within a CDI bean is done via @Reference annotations.

@Service(ConsumerService.class)
public class ConsumerServiceBean implements ConsumerService {

   @Inject
   @Reference
   private SimpleService service;

   public void consumeSomeService(String consumerName) {
      service.sayHello("Hello " + consumerName);
   }
}

By default, SwitchYard expects a service reference to be declared with a name which matches the Java type used for the reference.  In the above example, the SimpleService type would require a service reference in your SwitchYard configuration called "SimpleService".  In the event where the service reference name is different from the type name of the contract, the @Reference annotation can accept a service name:

@Reference("urn:myservices:purchasing:OrderService")
private OrderService orders;

ReferenceInvoker

The default behavior of @Reference is to inject a reference using the Java interface of the reference contract (SimpleService in the above example).  This is adequate for most cases, but it does not allow you to access SwitchYard API constructs like the Message and Context interfaces.  If you need to access to an attachment or a context property when invoking a reference from a Bean service, then you will want to use a ReferenceInvoker.  To use a ReferenceInvoker, all you need to do is replace the service contract interface type with a ReferenceInvoker type and SwitchYard will automatically inject the correct instance.  Here's a revised example which uses a ReferenceInvoker instance to invoke "SimpleService":

@Inject 
@Reference("SimpleService")
private ReferenceInvoker service;

public void consumeSomeService(String consumerName) {
   service.newInvocation("sayHello")
      .setProperty("myHeader", "myValue")
      .invoke(consumerName);
}

Note how the ReferenceInvoker instance is used to create a ReferenceInvocation using the newInvocation() method.  A new instance of ReferenceInvocation should be created each time you want to invoke a service using ReferenceInvoker.

Invocation Properties

While it's a best practice to write your service logic to the data that's defined in the contract (the input and output message types), there can be situations where you need to access contextual information like message headers (e.g. received file name) in your implementation.  To facilitate this, the Bean component allows you to access the SwitchYard Exchange Context instance associated with a given Bean Service Operation invocation. To get a reference to the Context, simply add a Context property to your bean and annotate it with the CDI @Inject annotation.

@Service(SimpleService.class)
public class SimpleServiceBean implements SimpleService {

@Inject
private Context context;

public String sayHello(String message) {
        System.out.println("*** Funky Context Property Value: " + context.getPropertyValue("funkyContextProperty"));
        return "Hi there!!";
    }
}

The Context interface allows your bean logic to get and set properties in the context.  Note that you can only make calls on the Context instance within the scope of one of the Service Operation methods. Invoking it outside this scope will result in an UnsupportedOperationException being thrown.

Implementation Properties

In contrast to invocation properties, implementation properties represent environmental properties that you have defined in the SwitchYard application descriptor (switchyard.xml) for your bean implementation.  To access these properties, simply add an @Property annotation to your bean class identifying the property you want to inject. The following example demonstrates injection of a "user.name" property:

@Service(SimpleService.class)
public class SimpleServiceBean implements SimpleService {

@Property(name="user.name")
private String name;

public String sayHello(String message) {
        return "Hello " + name + ", I got a message: " + message;
    }
}

        

See the Properties section of the User Guide for more information about SwitchYard property support.

Fault propagation on IN_ONLY

If the MEP of the service is IN_ONLY, Bean service just ignores the fault by default. If you want to propagate the fault back to service consumer, then you need to use IN_OUT MEP instead, or set "org.switchyard.propagateExceptionOnInOnly" property to true in your application domain. Domain properties are set via entries in the <domain> section of switchyard.xml.

<domain>
    <properties>
        <property name="org.switchyard.propagateExceptionOnInOnly" value="true"/>
    </properties>
</domain>
JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-13 09:45:30 UTC, last content change 2014-12-04 15:25:30 UTC.