adam bien's blog

Simplest Possible EJB 3.1 / REST (JSR-311) Component 📎

The component realization resides in the package: [...].business.orderprocessor. It is deployed as a WAR. The business is the name of the layer/tier and the orderprocessor the component's realization. Why this packages? It is easier to manage dependencies between them during the continuus integration. 

The component "orderprocessor" is organized internally in three, technical layers - also realized as packages: 

  • boundary: the external visible contract, the actual facade
  • control: the actual business logic implementation
  • entity: the persistence

Each package represents a responsibility and helps you also to measure the dependencies inside the component. E.g. elements from the entity package should not access the control or boundary.  

The boundary is implemented as a no-interface view @Stateless EJB 3.1: 


@Path("/orders/")
@Interceptors(CallAudit.class)
@Stateless public class OrderService {

    @EJB BillingService billing;
    @EJB DeliveryService delivery;
    @EJB Warehouse warehouse;

    @PUT
    @Produces({"application/xml","application/json"})
    @Consumes({"application/xml","application/json"})
    public Order order(Order newOrder){
        Order order = warehouse.checkout(newOrder);
        billing.payForOrder(order);
        delivery.deliver(order);
        return order;
    }

    @GET
    @Path("{orderid}/")
    @Produces({"application/xml","application/json"})
    public Order status(@PathParam("orderid") long orderId){
       return delivery.status(orderId);
    }
}

The functionality is directly exposed via REST, so there is no need to introduce dedicated interfaces. The OrderService starts transactions, can be decorated with cross-cutting aspects and represents the single entry point. Its a facade.

An element from the control layer simply relies on the existence of transactions - it is always executed in the boundary context. 


@Stateless
public class DeliveryService {

    @PersistenceContext
    EntityManager em;

    public void deliver(Order order){
        System.out.println("Delivered: " + order);
        order.setDelivered(true);
    }


    public Order status(long orderId) {
        Order found = this.em.find(Order.class, orderId);
        if(found == null)
            found = new Order();
        return found;
    }
}


The entity layer consists of JPA-entities, either domain driven, or procedural.

@Entity
@Table(name = "T_ORDER")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @XmlElement
    private long id;
    @XmlElement
    private int amount;
    @XmlElement
    private int productId;
    @XmlElement
    private boolean delivered;

    public Order() {
    }

    public Order(int amount, int productId) {
        this.amount = amount;
        this.productId = productId;
    }

    public boolean isDelivered() {
        return delivered;
    }
    
    public void setDelivered(boolean delivered) {
        this.delivered = delivered;
    }
}

The Order entity is also annotated with JAXB-annotations - what allows its serialization via XML or JSON without any additional work. In real world you will probably have to introduce a DTO to separate the different aspects of DB and XML serialization. 

EJB 3.1 and JSR-311 (REST) fit perfectly together. You can expose EJB 3.1 directly as REST-facades and gain single-threaded programming model, transactionality etc. The dependency to the EJB 3.1 API is very low (two annotations) - you could even go without any annotation.

The JUnit-tests are simple as well: 

[...]
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class OrderServiceTest { private OrderService orderService; @Before public void initOrderService() { this.orderService = new OrderService(); this.orderService.billing = new BillingService(); this.orderService.delivery = new DeliveryService(); this.orderService.warehouse = mock(Warehouse.class); } @Test public void testOrder() { Order order = new Order(2, 1); when(this.orderService.warehouse.checkout(order)).thenReturn(order); Order ordered = this.orderService.order(order); assertNotNull(ordered); assertTrue(ordered.isDelivered()); } }

The whole sample (LeanServiceECBComponent), tested with Netbeans 6.7.1/6.8m1 and Glassfishv3, was pushed into: http://kenai.com/projects/javaee-patterns/  After opening the LeanServiceECBComponent in Netbeans6.8(m1), right mouse-click on the project and choose "Test RESTFul Web Services".

This component is also described in the current JavaMagazin issue in more detail.

[The whole book "Real World Java EE Patterns - Rethinking Best Practices" describes lean Java EE architectures and patterns. See ServiceFacade, Service, PDO patterns and the chapter 6 "Pragmatic Java EE Architectures", Page 253]