|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 5 of 7
As in the case of servant activators, the POA makes several guarantees to prevent race situations from occurring in multithreaded
environments. For example, the request that causes preinvoke() to execute is the only request that will be processed using the servant returned by preinvoke(). Once that request is done, the POA will call postinvoke(). Furthermore, the same thread is used for both preinvoke() and postinvoke() calls for a given request.
Here is an example servant activator implementation that registers with the AccountPOA:
package bank;
import java.util.logging.Logger;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.ServantLocatorPackage.CookieHolder;
public class AccountServerLocatorImpl extends org.omg.PortableServer.ServantLocatorPOA
{
public Servant preinvoke(byte[] oid, POA adapter,
String operation, CookieHolder the_cookie) throws ForwardRequest
{
// First check the DB to make sure account exists.
// Then create an accountimpl and return.
System.out.println("(AccountServerLocatorImpl) Returning an Account Object for account number "
+ new String(oid));
try
{
DBUtils.getBalance(new String(oid));
}
catch(Exception e)
{
System.out.println("(AccountServerLocatorImpl) Oops... Invalid account number " + new String(oid));
throw new org.omg.CORBA.OBJECT_NOT_EXIST();
}
return new AccountImpl(new String(oid));
}
public void postinvoke(byte[] oid, POA adapter,
String operation, java.lang.Object the_cookie, Servant the_servant)
{
}
}
The preinvoke() method implementation resembles the servant activator's incarnate() method implementation. Similarly, postinvoke() is identical to etherialize() in the servant activator. The similarity does not end there. The account servant implementation is the same as well; it's
the same class—AccountImpl—used by the servant activator.
The final way to configure an AccountPOA is to use a default servant, which you register with the AccountPOA. It doesn't matter whether the AccountPOA has the RETAIN or NON_RETAIN policy. If it uses the RETAIN policy, then the AccountPOA uses the default servant only when a servant is not in the active object map. If the AccountPOA uses NON_RETAIN, then all requests forward to the default servant. The default servant must be thread safe, that is, it must not hold an
object-specific state. An implementation of an account default servant is shown below:
package bank;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
public class AccountDefaultServantImpl extends bank.AccountPOA
{
public AccountDefaultServantImpl()
{
}
public float balance()
{
try
{
return DBUtils.getBalance(accountNumber());
}
catch(Exception e)
{
return (float)-1.0;
}
}
public String accountNumber()
{
return new String(this._object_id());
}
public bank.AccountType accountType ()
{
try
{
return DBUtils.getAccountType(accountNumber());
}
catch(Exception e)
{
return AccountType.NIL;
}
}
public void deposit (float amt) throws bank.InvalidOperationException, bank.UnknownException
{
if(amt <= (float)0.0)
throw new InvalidOperationException("Invalid deposit amount of " + amt + " dollars.");
float balance = balance();
if(balance < 0)
throw new bank.UnknownException("Could not retrieve balance for Account " + accountNumber());
balance += amt;
try
{
DBUtils.setBalance(accountNumber(),balance);
}
catch(Exception e)
{
throw new bank.UnknownException(e.getMessage());
}
}
public void withdraw (float amt) throws bank.InvalidOperationException, bank.UnknownException
{
if(amt <= (float)0.0)
throw new InvalidOperationException("Invalid withdrawal amount of " + amt + " dollars.");
float balance = balance();
if(balance < 0)
throw new bank.UnknownException("Could not retrieve balance for Account " + accountNumber());
if(amt > balance)
throw new InvalidOperationException("Cannot withdraw more than account balance.");
balance = balance() - amt;
// Update the balance
try
{
DBUtils.setBalance(accountNumber(),balance);
}
catch(Exception e)
{
throw new bank.UnknownException(e.getMessage());
}
}
}
The above implementation differs from the other two solutions' account servants (AccountImpl instances) in that no account number member variable is in the default account servant class. To compensate for the lack
of an account number member variable, the default servant class has two major changes, which are outlined below: