What's a Bean Component?
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.
Providing a Service
Providing a service with the Bean component is as simple as adding an @Service annotation to your bean.
@Service(SimpleService.class) public class SimpleServiceBean implements SimpleService { public String sayHello(String message) { System.out.println("*** Hello message received: " + message); return "Hi there!!"; } } public interface SimpleService { String sayHello(String message); }
The SimpleService interface represents the Service Interface, defining the service operations that are exposed by SwitchYard.
The only other thing you need is a META-INF/beans.xml file in your deployed application. When the application is deployed, the Weld runtime scans the application for beans and enlists the SwitchYardCDIServiceDiscovery CDI extension in the CDI lifecycle. Our extension will pick 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.
Consuming a Service
Consuming a SwitchYard service from within a CDI bean is done via @Reference annotations.
@Service(ConsumerService.class) public class ConsumerServiceBean implements ConsumerService { @Reference private SimpleService service; public void consumeSomeService() { service.sayHello("Mustache"); } } public interface ConsumerService { void consumeSomeService(); }
Note that the contract for the service is all that's exposed to the bean consumer. The reference could point to a service that is hosted outside of SwitchYard and exposed 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 mechansim.
The @Reference annotation can accept a service name in cases where the default name resolution (interface Class simple name e.g. "OrderService") are not appropriate.
@Reference("urn:myservices:purchasing:OrderService") private OrderService orders;
This can be useful when the default name resolution is not appropriate. Keep in mind that the name used by the reference is not required to match the target service, but it resolve to a service through some mechanism. For example, the deployed application could contain wiring configuration which maps the service name used by the bean reference to a different service name in the runtime.
Unit Testing
Unit testing in SwitchYard is very easy. See the Testing SwitchYard Services documentation.
Try It Out
Easiest way to get started is to create a new application using the SwitchYard application archetype. Generating a new application from the archetype gets you a pom with the right dependencies for SwitchYard, a beans.xml definition in META-INF, a switchyard.xml file and a sample Bean service.
MyFirstApp/ pom.xml src/main/java org/switchyard/example/app SimpleService.java SimpleBeanService.java src/main/resources META-INF/ beans.xml src/test/java
Comments