|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 2 of 6
SOA implies distribution of services, which is not always necessary or desirable in a Java EE application. It would be foolish to access a local service remotely just to satisfy some high-level SOA concepts. Direct local access should always be preferred over remote services. A local call is not only orders of magnitude faster than a remote one; the parameters and return values can also be accessed "per reference" and need not be serialized.
Whether the service is local or remote, the business logic should always be executed consistently. A component needs a dedicated remoting and transaction boundary interface, which acts as a gatekeeper (see Figure 1). The main responsibility of such a facade is to keep the granularity of the methods coarse and the persistent state of the component consistent.

You can achieve the right granularity only by carefully crafting the interface so that consistency can be easily ensured with built-in transactions. Listing 1 shows how to configure declarative transactions and expose a remote business interface.
package ...bookstore.business.ordermgmt.facade;
@Stateless
@Remote(OrderService.class)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class OrderServiceBean implements OrderService {
@EJB
private CrudService crudService;
@EJB
private VatCalculator vatCalculator;
@EJB
private PriceCalculator pc;
@EJB
private OrderProcessor op;
@EJB
private ShipmentService shipmentService;
public Shipment orderBook(int customerId,int isbn){
BigDecimal priceNoVat = this.pc.computePrice(customerId, isbn);
BigDecimal price = this.vatCalculator.computeVat(priceNoVat);
Order o = this.op.processOrder(customerId, customerId, price);
return this.shipmentService.deliver(o);
}
public Shipment findShipment(long shipmentId){
return this.shipmentService.find(shipmentId);
}
//some methods omitted
}
Applying the @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) annotation to the class causes all methods to inherit this setting automatically. You could, alternatively, rely on the default
(which is TransactionAttributeType.REQUIRED) and not specify a transaction setting. However, the OrderService is the transaction and remoting boundary. It is accessed exclusively by the UI, which must not start any transactions. Using
the REQUIRES_NEW attribute is more explicit. It always starts a new transaction, which is what you would expect from a boundary. The REQUIRED configuration, if it were invoked without a transaction context, would reuse an existing transaction or start a new one.
A boundary, however, will never be invoked in an existing transaction, which makes the default setting more confusing.
The @Remote annotation is applied to the bean class -- not the business interface -- which may look strange at the first glance. The
business interface does not follow coding conventions either: its name doesn't contain the Remote suffix. As a result, the service consumer sees only a plain old Java interface and is not directly aware of using an EJB.
Only an indirect dependency on unchecked exceptions is present. If you are building a Web application, the OrderServiceBean would be exposed with a local business interface only, whereas a rich client runs in a separate process and requires a remote
interface. In either case there is no need to further emphasize the business interface's distributive capabilities. It gets
injected or looked up, and the consumer is only interested in the functionality and not its remote visibility.