Metadata Support for Transactional Web Services
maciej.machulak Jul 5, 2007 9:12 AMHi,
I have been working on support for transactional Web Services (with accordance to the Business Activity model described in the WS-BusinessActivity specification) for some time and I am close to releasing the first version of my framework. The framework is built on top of the XML Transaction Service (XTS) component of the JBoss Transaction Service. I will be setting up a Web site with the source code, documentation and some examples but first I would like to give you an overview of what and why has been done.
At this moment writing transaction-aware Web Services is relatively problematic and requires a lot of support from business programmers. Developers need to manually wire up original services with their compensation actions and must ensure the correctness of those links (e.g. in terms of data that needs to be shared). Moreover, it is necessary to follow transaction-related patterns where a developer must code not only the business logic but a participant as well. The latter one is an entity, which is capable of responding to transaction protocol messages (such as commit or compensate messages). Typically, a third component is also developed ? this component usually links participants with the business logic and is often referred to as the manager.
My aim was to facilitate development of transaction-aware Web Services and provide a comprehensive framework which would release programmers from mixing transaction-related code with business logic of their applications. The framework has a very clean API, which can be easily learnt and used. I will briefly describe it and show an example of how it can be used to expose an EJB component as a transaction-aware Web Service.
Programmer?s API
The API has been designed following the conventions proposed by the JSR-181 specification for exposing EJB components as Web Services. It consists of the following annotations:
@BAService ? specifies the service in terms of its state management;
@BAAgreementType ? specifies the agreement protocol the service wants to participate in;
@BACompensatedBy ? specifies the compensation action and a type of compensation;
@BAParam ? annotates the service?s parameter so that it can be processed by the compensation mechanism;
@BAResult ? annotates the service?s return value to be processed by the compensation mechanism;
@BACompensationManagement ? annotates a BA compensation manager object to enable transparent dependency injection.
Moreover, the programmer may use put(id,Object) and get(id) methods, which are invoked on the previously mentioned compensation manager to store and retrieve any additional data, which might be used for compensation.
Example
To understand how those annotations and methods can be used I will present an example of an EJB component (stateless session bean), which is exposed as a transaction-aware Web Service.
To expose a method as a transaction-aware Web Service, the business programmer must mark it with previously mentioned annotations as shown in the example below. If no additional data must be stored, then annotations are enough. The framework will transparently apply all necessary transaction mechanisms. If more flexibility needs to be achieved, the programmer may use additional methods (put() and get()) to store and retrieve any data that could be potentially used during compensation. The compensation action must only have its parameters annotated so that middleware mechanisms can match them with any data remembered during the execution of the original service (additional support for numerical identifiers is currently being developed so that the compensation action will not need to have any annotations). As shown in the example, the compensation action does not need to be transaction-aware. Moreover, it does not need to be exposed as a Web Service at all.
@Stateless @Remote(HotelBA.class) @WebService(name="HotelBA") @SOAPBinding(style = SOAPBinding.Style.RPC) @HandlerChain(file = "jaxws-ba-handler-server.xml") public class HotelBAImpl implements HotelBA { @BACompensationManagement private CompensationManager cm; @WebMethod @BAService(BAServiceType.MODIFY) @BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION) @BACompensatedBy(value="cancel",type = BACompensationType.CUSTOM) @BAResult("resNo") public Integer book(@BAParam("user")String user, @BAParam("pass")String pass, Integer room) { // ... business logic cm.put("charge",5); // ... business logic return reservationNumber; } @WebMethod public void cancel(@BAParam("user")String user, @BAParam("pass")String pass, @BAParam("resNo")Integer rNumber) { // ... business logic Integer refund = (Integer) cm.get("refund"); if (refund != null) { // ... business logic } // ... business logic } }
Future releases of the framework will provide support for remote compensation and will allow specifying transaction-related requirements in XML files (to allow exposing existing components).
I hope that the overview and example provided enough information to give a flavour of what the framework is aiming to achieve. Information about the first release and a link to the website will be posted here as soon as everything is ready.
Maciej Machulak