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
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:
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:
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.
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:
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":
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.
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.
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.
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:
See the Properties section of the User Guide for more information about SwitchYard property support.
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.