April 11, 2009, 11:33 p.m.
posted by hashspark
Exercise 11.1: Stateless Session BeanThis exercise utilizes the ProcessPayment EJB described in Chapter 11 of the EJB book. The code for this stateless bean is copied as is from Chapter 11, but a few additional classes are implemented to facilitate the example. Start Up JBossIf you already have JBoss running, there is no reason to restart it. Otherwise, start it up as instructed in Workbook 1. Initialize the DatabaseThe database tables will be created when Exercise 11.1 is deployed to JBoss. If you have problems running this example, shut down JBoss and run the clean.db Ant task. Build and Deploy the Example ProgramsPerform the following steps:
As in the exercises in earlier chapters of this workbook, titan.jar is rebuilt, copied to the JBoss deploy directory, and redeployed by the application server. Examine ProcessPaymentBeancom.titan.processpayment.ProcessPaymentBean is copied as is from Chapter 11. @Resource injection is very vendor-specific. Let's look at how JBoss supports this annotation:
package com.titan.processpayment;
import com.titan.domain.*;
import java.sql.*;
import javax.ejb.*;
import javax.annotation.Resource;
import javax.sql.DataSource;
import javax.ejb.EJBException;
@Stateless
public class ProcessPaymentBean implements ProcessPaymentRemote,
ProcessPaymentLocal
{
final public static String CASH = "CASH";
final public static String CREDIT = "CREDIT";
final public static String CHECK = "CHECK";
@Resource(mappedName="java:/DefaultDS")
DataSource dataSource;
When you use the @javax.annotation.Resource annotation or its XML equivalent, <resource-ref>, JBoss requires that you specify the mappedName( ) attribute. JBoss stores all resources in its global JNDI tree. The mappedName( ) attribute expects a global JNDI name string. The java:/DefaultDS value references JBoss's default data source. Appendix A provides more detail on how to deploy your own data sources. The mappedName( ) attribute is used in the same way to inject JMS destinations and connection factories. Examine DataAccessBeancom.titan.access.DataAccessBean is a simple stateless session bean that is used to find and create Customer entities. It also has methods to create and destroy the tables that are needed by the ProcessPayment EJB. We won't go over these because they are quite simple. Examine the ClientThe main client is the com.titan.clients.MakePayment class:
package com.titan.clients;
import com.titan.processpayment.*;
import com.titan.domain.Customer;
import com.titan.access.DataAccess;
import java.util.Calendar;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NamingException;
/**
* Example demonstrating use of ProcessPayment EJB directly
*
*/
public class MakePayment
{
public static void main(String [] args)
{
try
{
// obtain CustomerHome
Context jndiContext = getInitialContext( );
DataAccess access = (DataAccess)jndiContext.lookup("DataAccessBean/remote");
access.makePaymentDbTable( );
Customer cust = new Customer( );
cust.setFirstName("Bill");
cust.setLastName("Burke");
access.createCustomer(cust);
The client starts by getting a reference to the DataAccessBean's remote interface. It initializes the payment tables by calling the DataAccess.makePaymentDbTable( ) method and then creates a Customer entity:
ProcessPaymentRemote procpay =
(ProcessPaymentRemote)jndiContext.lookup("ProcessPaymentBean/remote");
After obtaining a reference to the ProcessPayment EJB's remote interface, three separate payments are made by cash, check, and credit card for the Customer entity that was created:
System.out.println("Making a payment using byCash( )..");
procpay.byCash(cust,1000.0);
System.out.println("Making a payment using byCheck( )..");
CheckDO check = new CheckDO("010010101101010100011", 3001);
procpay.byCheck(cust,check,2000.0);
System.out.println("Making a payment using byCredit( )..");
Calendar expdate = Calendar.getInstance( );
expdate.set(2025,1,28); // month=1 is January
CreditCardDO credit = new CreditCardDO("370000000000002",
expdate.getTime( ),"AMERICAN_EXPRESS");
procpay.byCredit(cust,credit,3000.0);
System.out.println("Making a payment using byCheck( ) with a low
check number..");
CheckDO check2 = new CheckDO("111000100111010110101", 50);
try
{
procpay.byCheck(cust,check2,9000.0);
System.out.println("Problem! The PaymentException has not been raised!");
}
catch(PaymentException pe)
{
System.out.println("Caught PaymentException: "+pe.getMessage( ));
}
The last bit of code tries to make a check payment with a check number that is too low. A payment exception is thrown in this instance.
access.dropPaymentDbTable( );
}
catch(Throwable t)
{
t.printStackTrace( );
}
}
static public Context getInitialContext( ) throws Exception
{
return new InitialContext( );
}
}
The client finishes by dropping the payment table. Run the Client ApplicationRun the MakePayment application by invoking ant run.payment at the command prompt. Remember to set your JBOSS_HOME and PATH environment variables. This is the output:
run.payment:
[java] Making a payment using byCash( )..
[java] Making a payment using byCheck( )..
[java] Making a payment using byCredit( )..
[java] Making a payment using byCheck( ) with a low check number..
[java] Caught PaymentException: Check number is too low. Must be at least 100
|
- Comment