Browse DevX
Sign up for e-mail newsletters from DevX


Make the Right Decision with Our Side-by-Side Comparison of Spring and EJB 3.0 : Page 4

Are you trying to choose between Spring and EJB 3.0? If you are you know what a hard decision it can be. Explore the similarities and differences between two of the most popular Java technologies today and learn key distinctions in making a technological decision between the two.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

One of the more characteristic differences between Spring and EJB 3.0 is their respective approaches to managing state. State is an important element to many applications because a user's interaction with the system typically involves a series of steps with cumulative meaning. For example, in the context of the example flight booking application, while booking a ticket a customer navigates between browsing for flights, selecting seat assignments, and providing payment information. As the user navigates between these steps the choices made in previous steps are implicit in the context of the conversation.

Recognizing the important role state plays in many applications, EJB provides a first level construct, the Stateful Session Bean (SFSB), dedicated to managing a stateful conversation. With SFSBs subsequent invocations of a bean share the bean instance and thus the same state. SFSBs are also designed with issues of scalability and fail-over in mind although the implementation of many of these concerns are left to specific vendor implementations. Spring does not offer any direct equivalent to SFSBs although several approaches exist for accomplishing the same result.

Statefulness—Functional Comparison
To illustrate the approaches toward state offered by Spring and EJB 3.0 consider the sequence of steps involved in booking a ticket (see Figure 3).

Figure 3. Book Ticket Sequence Diagram. Passengers book tickets through a series of interactions with a booking agent. These steps are conversational and the context of the conversation (the state) evolves with each step.
The following unit test verifies that the booking agent can be interacted with in a stateful manner:

public void testPurchaseTicket_UseCase() throws Exception { // Begin purchase ticket conversation FlightCriteria flightCriteria = new FlightCriteria("DFW", "AUS", DateUtilities .parseDate("2006-01-15")); bookingAgent.bookRoundTripTicket(flightCriteria); // Select outbound flight List outboundFlights = bookingAgent.listOutboundFlights(); assertEquals(3, outboundFlights.size()); bookingAgent.selectOutboundFlight(selectFlight(outboundFlights, 1)); // Select return flight List<Flight> returnFlights = bookingAgent.listReturnFlights(); assertEquals(3, returnFlights.size()); bookingAgent.selectReturnFlight(selectFlight(returnFlights, 2)); // Select passenger Passenger passenger = new Passenger("Rod", "Coffin"); bookingAgent.selectPassenger(passenger); // Select seats bookingAgent.selectOutboundSeat(selectSeat(bookingAgent.retrieveCurrentTicket() .getOutboundFlight(), "1B")); bookingAgent.selectReturnSeat(selectSeat(bookingAgent.retrieveCurrentTicket() .getReturnFlight(), "1A")); // Purchase ticket Ticket ticket = bookingAgent.purchaseTicket(); assertTrue(ticket.getId() != 0); }

Both Spring and EJB 3.0 can satisfy this unit test. The Spring implementation is shown below:

public class BookingAgentSpring implements BookingAgent { private FlightCriteria outboundCriteria; private FlightCriteria returnCriteria; private Ticket ticket; public Ticket bookRoundTripTicket(FlightCriteria flightCriteria) { outboundCriteria = flightCriteria; returnCriteria = reverseCriteria(flightCriteria); ticket = new Ticket(); ticketDAO.save(ticket); return ticket; } ... }

In order for Spring-managed beans to contain state, instances cannot be shared between callers. To accomplish this, the scope of stateful beans in Spring should be configured as prototype. This means that each time a bean is retrieved from a bean factory a new instance is created.

<bean id="bookingAgentSpring" scope=”prototype” class="org.jug.flight.booking.spring.BookingAgentSpring"> ... </bean>

Compare with the EJB 3.0 implementation:

@Stateful public class BookingAgentEJB implements BookingAgent { private FlightCriteria outboundCriteria; private FlightCriteria returnCriteria; private Ticket ticket; public Ticket bookRoundTripTicket(FlightCriteria flightCriteria) { outboundCriteria = flightCriteria; returnCriteria = reverseCriteria(flightCriteria); ticket = new Ticket(); ticketDAO.save(ticket); return ticket; } ... }

In both cases the booking agent can store state and participate with the caller in a conversational manner. So it is possible to create stateful behavior with both Spring and EJB 3.0 but the approaches and implications of these approaches differ significantly with one another.

Statefulness - Non-Functional Comparison
The examples above illustrate how stateful objects could be implemented in both Spring and EJB 3.0. Although functionally equivalent there is a significant difference in how state is managed. In the Spring implementation the caller stores the complete booking agent (see Figure 4), whereas in the EJB 3.0 implementation the caller is merely storing a proxy to the booking agent (see Figure 5). Because the caller in the EJB 3.0 version is only holding onto a proxy, the SFSB and its associated state exists within—and is managed by—the server.

Figure 4. Client Managed State. One approach to implementing stateful beans with Spring is to store the stateful component in the HttpSession managed by the web container.
Figure 5. EJB Managed State. Clients interact with EJB components via proxies. This allows the component's state to be managed by the EJB container.

There are several advantages to the EJB approach with SFSBs. First, SFSB are designed to optimize server performance by allowing SFSBs to be swapped between memory and persistence storage. This allows application servers to balance resources to achieve optimal performance. Secondly, SFSBs can be run in a separate process from the caller. This might be performed to allow tiers of an application to be scaled independently or for security purposes. Thirdly, SFSBs may also implement the optional SessionSynchronization interface to in order to rollback bean state in response to a transaction rollback event.

One of the major criticisms typically heaped on SFSBs is that they do not perform or scale as well as stateless architectures. In response to this, the Spring framework is primarily a stateless framework. But given that state is an important part of many applications, there has to some options for expressing state. Typical approaches include putting state in the database, the HTTP Session, or in an in-memory cache. In the example above, the stateful Spring booking agent could be stored in either of these vehicles. But each of these options has its own disadvantages, as shown in Table 4.

Table 4. Alternatives to Stateful Session Beans in Spring.

SFSB Alternative Advantages Disadvantages
Database Shared by all application servers. Usually the least scalable tier of an application. If using a second-level cache then data must be replicated.
HTTP Session Simple to use. Data must be replicated and is not transaction aware.
Memory Cache Shared by all application servers, potentially more efficient then using the database. Data must be replicated and is not transaction aware.

The scalability argument applied against SFSBs can also be applied to each of these three alternatives to SFSBs (as shown in Table 4). In addition you must spend considerable development effort re-implementing functionality already provided by SFSBs. These tradeoffs should be considered seriously when deciding upon your application's approach to state.

Both Spring and EJB 3 offer hooks that allow developers to tie into the lifecycle of managed beans. Spring provides the InitializingBean and DisposableBean interfaces, which provide hooks to notify beans after they have been initialized by Spring and before destruction. Similarly, EJB components can optionally receive notifications after creation, before destruction, before passivation, and after activation.

Lastly, the issue of how to synchronize the conversational state of a bean with the status of a transaction is one that must be resolved, whether using SFSBs or an alternative. By default, when a transaction rolls back, all transactional resources participating in the transaction (such as database and messaging systems) roll back as well. But the state of the beans involved will not be rolled back. If these beans are stateful then they will be out of sync with the persistence data store. EJB 3.0 SFSBs using container-managed transactions can implement the SessionSynchronization interface to be notified of transactional events. Spring does not offer equivalent functionality but it could be handled in some custom way by the application.

Both Spring and EJB 3.0 enable stateful applications. In an EJB 3.0 application the primary mechanism for accomplishing this is the use of SFSBs. Spring is primarily a stateless architecture but can facilitate statefulness through prototype beans. Applications using this approach need to consider its implications for performance and scalability and will need some other method of addressing the issues handled by SFSBs.

Table 5. Differences in State-handling Between Spring and EJB 3.0.

Feature Spring EJB 3.0
Stateful construct Prototype (instance) beans Stateful Session Bean
Instance Management Singleton, prototype, request, session, global session Instance per lookup
Lifecycle Management √ (Initialization/Destruction) √ (Creation/Destruction, Activation/Passivation)
Transaction awareness -- √ (SessionSynchronization interface)
Standard N/A

Thanks for your registration, follow us on our social networks to keep up-to-date