1. Trang chủ
  2. » Công Nghệ Thông Tin

Building Java Enterprise Applications Volume I: Architecture phần 7 pps

25 305 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 25
Dung lượng 429,46 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

public float getBalanceint accountId throws RemoteException { Context context = new InitialContext ; // Look up the Account bean AccountHome accountHome = AccountHome public Collec

Trang 1

public float getBalance(int accountId) throws RemoteException {

Context context = new InitialContext( );

// Look up the Account bean

AccountHome accountHome = (AccountHome)

public Collection findByUserId(Integer userId)

throws FinderException, RemoteException;

The accompanying query element in the Account bean's entry in the ejb-jar.xml descriptor

would look like this:

Trang 2

8.3.2 Going Stateless

To move this bean into stateless territory, you first need to change the home interface's create( ) signature Since stateless beans can't maintain any information between method calls, passing in a username (or any other data) to the create( ) method is useless Make the following change:

public AccountManager create( )

throws CreateException, RemoteException;

Once this change has been made, you need to determine which methods advertised by the bean require a username for operation In other words, browse through your bean's implementation class and note any method that uses the username or user method variable Once you've determined the methods in this category, you will need to change the signature for those methods in the remote interface:

public interface AccountManager extends EJBObject {

public AccountInfo add(String username, String type, float balance)

throws RemoteException, UnknownAccountTypeException;

public float getBalance(int accountId) throws RemoteException;

public boolean delete(int accountId) throws RemoteException;

Trang 3

your bean implementation class to operate without maintaining state First, add a utility method to the end of the class:

private User getUser(String username) throws RemoteException {

try {

// Get an InitialContext

Context context = new InitialContext( );

// Look up the Account bean

UserHome userHome = (UserHome)

public void ejbCreate( ) throws CreateException {

// Nothing to be done for stateless beans

// Get the correct user

User user = getUser(username);

// Look up the Account bean

AccountHome accountHome = (AccountHome)

public List getAll(String username) {

List accounts = new LinkedList( );

try {

User user = getUser(username);

Integer userId = user.getId( );

// Get an InitialContext

Trang 4

// Look up the Account bean

AccountHome accountHome = (AccountHome)

context.lookup("java:comp/env/ejb/AccountHome");

Collection userAccounts = accountHome.findByUserId(userId);

for (Iterator i = userAccounts.iterator(); i.hasNext( ); ) {

Account account = (Account)i.next( );

Trang 5

Example 8-10 An AccountManager Helper Class

/** The username for this account's user */

private String username;

/** The <code>AccountManager</code> bean instance */

private AccountManager manager;

public AccountManagerHelper(String username)

throws CreateException, NamingException, RemoteException {

// Get the stateless bean instance

Object ref = context.lookup("forethought.AccountManagerHome"); AccountManagerHome accountManagerHome = (AccountManagerHome)

PortableRemoteObject.narrow(ref, AccountManagerHome.class); this.manager = accountManagerHome.create( );

}

public AccountInfo add(String type, float balance)

throws RemoteException, UnknownAccountTypeException {

Trang 6

public AccountInfo withdraw(AccountInfo accountInfo, float amount) throws RemoteException {

// Look up the AccountManager bean

System.out.println("Looking up the AccountManager bean.");

// Get all accounts

List accounts = accountHelper.getAll( );

for (Iterator i = accounts.iterator(); i.hasNext( ); ) {

AccountInfo accountInfo = (AccountInfo)i.next( );

System.out.println("Account ID: " + accountInfo.getId( ));

System.out.println("Account Type: " + accountInfo.getType( ));

Trang 7

// Delete account

accountHelper.delete(everydayAccount.getId( ));

System.out.println("Deleted everyday account.");

You may find that helper classes like this can simplify your own client code, even if you don't

need to provide stateful session bean masquerading, where a stateless bean is made to look

like a stateful one In any case, this approach provides the best of both session bean types: the performance of a stateless bean with the interface of a stateful one This technique will allow you to convert all of your application's stateful session beans into stateless ones, which will yield some dramatic performance improvements

8.4 What's Next?

You now have the tools to build the back-end of almost any enterprise application you may come across, and apply your knowledge to most of the problems you will encounter in the enterprise Java space In the next chapter, though, I want to move beyond the basics into the less-used realm of the Java Message Service (and specifically, message-driven beans) Although it is still somewhat unusual to see these kinds of beans in action, you will find that JMS offers several attractive features I'll detail these and how they can help in asynchronous tasks in the next chapter, which focuses specifically on messaging in enterprise applications

Trang 8

Chapter 9 Messaging and Packaging

Up until now, everything detailed in the Forethought application has been based on

synchronous processing This simply means that an event is triggered by some client, then

responded to by an application component, and finally an answer is returned to that client For example, when a Java class requests that a new user be created, the UserManager accesses the User bean, that bean interacts with the database, and an acknowledgment is triggered back up the calling stack The extensive coverage of this type of interaction is justified, as you will be dealing with synchronous processing far more often than not

However, there are times when you want more of a listener paradigm In this case, an application component waits for certain types of events and responds only when those events

occur That component is called a listener, because it listens for application events When it is

activated, it takes some sort of action, often interacting with various other components in the application It typically does not send any acknowledgment when its actions are done, making

it asynchronous in operation I'll detail this sort of behavior in this chapter, focusing on the scheduling component of the Forethought application Meetings will be added to the Forethought queue and reported to a scheduling client, which simply spits these meetings back out to waiting recipients

Additionally, this chapter will wrap up some loose ends by detailing the final packaging of the enterprise beans detailed in this and previous chapters This will fill in the blanks on assembly descriptors, method permissions, and other deployment descriptor options previously left uncovered At the end of this chapter, you'll have a complete, working application foundation, ready for use

9.1 Messaging on the Server

To begin the discussion on messaging, I want to focus on the scheduling component of the Forethought application Specifically, I want to look at messaging components on the server

By "the server," I simply mean the back-end of the application, as distinguished from any set

of application clients This may or may not be a separate physical machine, but in either case,

it is distinct from application clients such as desktop programs or other application interface tools Once you understand how this messaging operates within the application, you will be ready for the next section, where clients are discussed and built

9.1.1 Premise

First, let's revisit the scheduler facility for the Forethought application The application should

be able to store events that are important to the company As you recall from Chapter 3, the EVENTS table is set up for just such a purpose Then, users in the Forethought application are associated with these events and become attendees (not surprisingly, stored in the ATTENDEES table) This is all fairly basic material

Scheduling comes into play when you realize that individual employees will probably run some type of calendar or scheduling software on their computers For the sake of this discussion, assume that this software is customizable, and that you can add features to it That

is important, as it allows the messaging and scheduling components in the application to be hooked into their desktop software Given that assumption, the task becomes clear

Trang 9

Each time a new event is added to the data store, a message should be fired off This message should indicate that a new event has been created, and also include the attendees for that event Since you should already have an Event entity bean (from Appendix E), it is fairly easy

to extrapolate the need for a session bean to handle the addition of data to that bean, as discussed in the last chapter I'll call this session bean Scheduler While it could have been called EventManager, I've used a different name to indicate that it is not a simple administrative component, as the other manager beans were This component will handle creation of events, and then send off a Java Message Service (JMS) message indicating this creation

The purpose of this message is simple: it allows any application client subscribed to the same JMS topic to which these messages are sent to consume the new message The client can examine the new event, and if the event has a certain individual as an attendee, it can sound

an alarm, send email, or otherwise notify the relevant attendee I'll delve into specific examples of these actions in Section 9.2 However, understand that once your component makes these messages available through JMS, the possibilities for client interaction become nearly limitless

9.1.2 The EventManager Bean

Actually putting these principles into practice is not nearly as complex as you might expect First, you should already have the Event bean coded from Appendix E You'll then need to code up a manager session bean to allow access to this entity I've kept this bean extremely simple, as it's not the focus of this discussion Example 9-1 shows the remote interface for this new manager

Example 9-1 The EventManager Remote Interface

public interface EventManager extends EJBObject {

public EventInfo addEvent(String description, Date dateTime,

Trang 10

Example 9-2 The EventManager Home Interface

package com.forethought.ejb.event;

import java.rmi.RemoteException;

import javax.ejb.CreateException;

import javax.ejb.EJBHome;

public interface EventManagerHome extends EJBHome {

public EventManager create( )

throws CreateException, RemoteException;

/** <p> Required method for allowing bean lookups </p> */

public void ejbCreate( ) throws CreateException {

// No action required for stateless session beans

Context context = new InitialContext( );

// Add event to database

EventHome eventHome = (EventHome)

Trang 11

// Get topic factory

// Send off notification of this event

Trang 12

Context context = new InitialContext( );

// Look up the User bean

EventHome eventHome = (EventHome)

Trang 13

the message body Additionally, some indication of what action has occurred needs to be included Rather than putting this application-specific data into the information map, a string property of the message is set, which will be decoded by message recipients The result is a simple yet useful message that is broadcast upon creation and deletion of events in the Forethought system This completes the EventManager bean, and allows us to move on to a message-driven bean that will consume and use these messages

9.1.3 Business Logic and Messaging Logic

As in the case of using pure JMS, described in the last section, I am not going to discuss the basics of message-driven beans Instead, I'll simply show you a new bean for your application, the Scheduler bean, which consumes messages from the EventManager bean just created One nice thing about message-driven beans is that they are completely server-based components This means that no remote or home interface is required Given that, Example 9-4 jumps straight to the implementation code for this new bean

Example 9-4 The Scheduler Bean

public class SchedulerBean implements MessageDrivenBean {

/** The context for the message-driven bean, set by the EJB container

*/

private MessageDrivenContext messageContext;

/** Required creation method for message-driven beans */

public void ejbCreate( ) {

// No action required for message-driven beans

}

Trang 14

/** Required removal method for message-driven beans */

public void ejbRemove( ) {

messageContext = null;

}

/** Required method for container to set context */

public void setMessageDrivenContext(MessageDrivenContext

// Convert to the correct message type

ObjectMessage objectMessage = (ObjectMessage)message;

// Dissect message

String action = objectMessage.getStringProperty("Action");

EventInfo eventInfo = (EventInfo)objectMessage.getObject( );

private void sendEventNotification(String action, EventInfo eventInfo)

throws JMSException, NamingException {

// Ensure that at least one employee involved

boolean hasEmployee = false;

for (Iterator i = eventInfo.getAttendees().iterator();

// Get the client topic destination

Context context = new InitialContext( );

Trang 15

// Send off notification of this event

TopicSession session =

connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicPublisher publisher = session.createPublisher(topic);

other publisher to the Scheduler topic It then sends out new messages to the Employee topic

(introduced for the first time here), using another ObjectMessage, through the sendEventNotification( ) method Given that this bean does little more than resend messages, you are probably wondering why it even exists This is a good question, and has a good answer

The EventManager bean could have easily sent messages directly to the Employee topic,

handling filtering on its own However, that assumes that no other action needs to be taken For example, a more advanced Scheduler bean might update a company-wide directory server with the event information, log the changes to a static text file, and update a scheduling database using entity beans This logic is specific to scheduling, not simple creation and addition of events If all of this scheduling logic were added into the EventManager component, it would quickly become unclear what code in that bean was specifically event-related, and what code was scheduling-related In other words, the bean would quickly cease

to be a simple manager/administrative component

Further, that scenario presumes that only the EventManager takes action related to scheduling It's plausible that other beans, Java classes, or messaging clients might also be able to update events, change attendees, or perform other scheduling-related actions By taking all scheduling-related code and placing it in a separate bean, any additional logic can be maintained in a single place (the Scheduler bean) Finally, this design allows changes to scheduling logic to occur without having to make the EventManager unavailable; if this happened, the EventManager would simply be sending messages out that would be consumed

at a later date (or not at all, as the case may be) In any case, it should be clear that separating your messaging logic from your data logic is critical, and explains the reasoning behind a separate Scheduler bean Don't be fooled by the simplicity of the current Scheduler implementation; things in a real-world system would quickly become more complex than shown here

You should now follow the appendixes' and your server's instructions to deploy these new components, including the message-driven bean Once those resources are in place, it's time to look at writing a standalone Java client that takes these messages and does something with them

Ngày đăng: 05/08/2014, 10:20

TỪ KHÓA LIÊN QUAN