|
|
State Design
Continuing on with the Forethought business logic,
package com.forethought.ejb.account;
import java.rmi.RemoteException;
import java.util.List;
import javax.ejb.EJBObject;
import com.forethought.ejb.account.AccountInfo; // Account bean
import com.forethought.ejb.accountType.UnknownAccountTypeException; // AccountType bean
public interface AccountManager extends EJBObject
{
public AccountInfo add( String type, float balance ) throws RemoteException, UnknownAccountTypeException;
public AccountInfo get( int accountId ) throws RemoteException;
public List getAll() throws RemoteException;
public AccountInfo deposit( AccountInfo accountInfo, float amount ) throws RemoteException;
public AccountInfo withdraw( AccountInfo accountInfo, float amount ) throws RemoteException;
public float getBalance( int accountId ) throws RemoteException;
public boolean delete( int accountId ) throws RemoteException;
}
As you can see, the manager operates upon a single account for a single user.
package com.forethought.ejb.account;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface AccountManagerHome extends EJBHome
{
public AccountManager create( String username ) throws CreateException, RemoteException;
}
This provides a means to create a new account or to find all existing accounts for a given username.
This is all basic EJB material, and should not cause you any problems.
To deploy the AccountManager bean, you would use this (additional) XML entry in your ejb-jar.xml deployment descriptor:
Additions to your application server's vendor-specific descriptors should be equally simple.
public interface AccountManager extends EJBObject
{
public AccountInfo add( String username, String type, float balance ) throws RemoteException, UnknownAccountTypeException;
public AccountInfo get( int accountId ) throws RemoteException;
public List getAll( String username ) throws RemoteException;
public AccountInfo deposit( AccountInfo accountInfo, float amount ) throws RemoteException;
public AccountInfo withdraw( AccountInfo accountInfo, float amount ) throws RemoteException;
public float getBalance( int accountId ) throws RemoteException;
public boolean delete( int accountId ) throws RemoteException;
}
In this case, only two methods require this information, so it is not terribly inconvenient.
private User getUser(String username) throws RemoteException
{
try
{
Context context = new InitialContext(); // Get an InitialContext
// Look up the Account bean
UserHome userHome = (UserHome) context.lookup("java:comp/env/ejb/UserHome");
User user = userHome.findByUserDn(LDAPManager.getUserDN(username));
return user;
}
catch (NamingException e)
{
throw new RemoteException("Could not load underlying User bean.");
}
catch (FinderException e)
{
throw new RemoteException("Could not locate specified user.");
}
}
Then remove the username and user member variables, and modify three methods (those affected by the change to stateless):
public void ejbCreate() throws CreateException
{
// Nothing to be done for stateless beans
}
public AccountInfo add(String username, String type, float balance) throws UnknownAccountTypeException
{
try
{
Context context = new InitialContext(); // Get an InitialContext
User user = getUser(username); // Get the correct user
// Look up the Account bean
AccountHome accountHome = (AccountHome) context.lookup("java:comp/env/ejb/AccountHome");
Account account = accountHome.create(type, balance, user);
return account.getInfo();
}
catch (RemoteException e)
{
return null;
}
catch (CreateException e)
{
return null;
}
catch (NamingException e)
{
return null;
}
}
public List getAll(String username)
{
List accounts = new LinkedList();
try
{
User user = getUser(username);
Integer userId = user.getId();
// Get an InitialContext
Context context = new InitialContext();
// 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();
accounts.add(account.getInfo());
}
}
catch (Exception e)
{
// Let fall through to the return statement
}
return accounts;
}
Finally, don't forget to change your deployment descriptor:
All things considered, these are relatively simple changes to make, and have the net effect of making your bean faster, more efficient,
package com.forethought.client;
import java.rmi.RemoteException;
import java.util.List;
import javax.ejb.CreateException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
// Account bean
import com.forethought.ejb.account.AccountInfo;
import com.forethought.ejb.account.AccountManager;
import com.forethought.ejb.account.AccountManagerHome;
// AccountType bean
import com.forethought.ejb.accountType.UnknownAccountTypeException;
public class AccountManagerHelper
{
private String username; /** The username for this account's user */
private AccountManager manager; /** The
Looking at the methods available on this helper class, you should realize pretty quickly that it mirrors the remote interface of the AccountManager session bean;
// Look up the AccountManager bean
System.out.println("Looking up the AccountManager bean.");
AccountManagerHelper accountHelper = new AccountManagerHelper("gqg10012");
// Create an account
AccountInfo everydayAccount = accountHelper.add("Everyday", 5000);
if (everydayAccount == null)
{
System.out.println("Failed to add account.\n");
return;
}
System.out.println("Added account.\n");
// 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());
System.out.println("Account Balance: " + accountInfo.getBalance() + "\n");
}
// Deposit
accountHelper.deposit(everydayAccount, 2700);
System.out.println("New balance in everyday account: " + accountHelper.getBalance(everydayAccount.getId()) + "\n");
// Withdraw
accountHelper.withdraw(everydayAccount, 500);
System.out.println("New balance in everyday account: " + accountHelper.getBalance(everydayAccount.getId()) + "\n");
// 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 do not need to provide stateful session bean masquerading, |