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] 

Comments:

Hi Adam,

you could also use @Mock Annotation.

Instead writing:

this.orderService.warehouse = mock(Warehouse.class);

You just add the @Mock Annotation to the OrderService Implementation:

@EJB @Mock Warehouse warehouse;

Then in the @Before Method of your Test you initializes the Mocks as follows:

MockitoAnnotations.initMocks(this.orderService);

This is great!

Regards,
Robert

Posted by Robert on August 11, 2009 at 02:47 PM CEST #

on OrderService you have 12 lines of annotations and something like 8 usual code. Fun! I guess it can be explained - it is a service and need some @ to activate. But, anyway, i could only notice that

Posted by Gabriel Kastenbaum on August 13, 2009 at 04:38 PM CEST #

How is the EntityManager inside DeliveryService initialized during the test?

Can I use Constructor-Injection to avoid those public fields annotated with EJB?

Posted by Sakuraba on August 14, 2009 at 08:55 PM CEST #

@Sakuraba,

you can use either constructors, or setters to set the EntityManager during the test. I just prefer to use the package-visibility - you can keep your code more concise,

adam

Posted by Adam Bien on August 14, 2009 at 11:13 PM CEST #

So you basically would add a persistence-unit xml-file for testing, start e.g. a local hsqldb instance before the test, create the EntityManagerFactory /EntityManager for this test-persistence-unit. Afterwards one could do "delivery.em = mytestEM;" inside the Before-methods or use EasyMock for the EntityManager alltogether.

Posted by Sakuraba on August 15, 2009 at 05:49 PM CEST #

@Sakuraba,

either that, or use Mockito to mock-out the EM entirely. You can easily factor out the creation of the EntityManager into a super class (2-liner). It works perfectly in real world.

Did you expected something else?

thansk,

adam

Posted by Adam Bien on August 16, 2009 at 12:21 AM CEST #

Well... actually yes, I didnt think it would be that easy.

Thanks for your responses ;)

Posted by Sakuraba on August 20, 2009 at 09:31 PM CEST #

Hi adam,

" In real world you will probably have to introduce a DTO to separate the different aspects of DB and XML serialization."

Do you know an existing example on how to do this?

Posted by JanVerbeke on December 26, 2009 at 06:21 PM CET #

@Jan,

sure - it is trivial plumbing. You will have to read the state of the DB entity in the boundary and copy the interesting contents into a XML- DTO,

This isn't mandatory - such approach often evolves during a project. I wouldn't start with a such separation. Start with a spike / poc then see whether your approach "feels right",

adam

Posted by Adam Bien on December 26, 2009 at 11:10 PM CET #

Hello Adam,

Using Wildfly 8.1 with Resteasy.
That is working fine.
Now I am trying to inject a bean into my restful-class and that is not working, though I annotate it with @Stateless.

very strange.
(1)
@Stateless
@Path("/json")
public class StudentResource {
@EJB(mappedName ="java:module/HelloBean" )
HelloBean bean;

@Stateless
@Path("/json")
public class StudentResource {

@EJB
HelloBean bean;

regards, i

Posted by Ingo on February 13, 2015 at 03:38 PM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
...the last 150 posts
...the last 10 comments
License