本示例是在Weblogic的示范example中进行修改的,模拟Trade的buy和sell的过程.
定义了四个Business方法,具体看Remote接口Trader.
另外定义了一个testLocal的方法用来测试Local接口(为什么要这么做,不明白的同学先看看Local的基本知识)
自定义买卖过程中出现的Exceptioin:ProcessingErrorException
封装买卖的结果PO:TradeResult
模拟客户端的买卖行为:Client
配置ejb-jar.xml和weblogic-ejb-jar.xml
1.Remote 接口 Trader.java
import java.rmi.RemoteException; import javax.ejb.EJBObject; public interface Trader extends EJBObject { public abstract TradeResult buy(String customerName, String stockSymbol, int shares) throws ProcessingErrorException, RemoteException; public abstract TradeResult sell(String customerName, String stockSymbol, int shares) throws ProcessingErrorException, RemoteException; public abstract double getBalance() throws RemoteException; public abstract double getStockPrice(String stockSymbol) throws ProcessingErrorException, RemoteException; public abstract double testLocal() throws RemoteException; }
2.Home 接口 TraderHome.java
import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; import javax.ejb.EJBObject; public interface TraderHome extends EJBHome { public Trader create() throws RemoteException,CreateException; }
3.Local 接口 TraderLocal.java
import javax.ejb.EJBLocalObject; public interface TraderLocal extends EJBLocalObject{ public abstract TradeResult buy(String customerName, String stockSymbol, int shares) throws ProcessingErrorException; public abstract TradeResult sell(String customerName, String stockSymbol, int shares) throws ProcessingErrorException; public abstract double getBalance() ; public abstract double getStockPrice(String stockSymbol) throws ProcessingErrorException; public abstract double testLocal(); }
4.LocalHome 接口 TraderLocalHome.java
import javax.ejb.CreateException; import javax.ejb.EJBLocalHome; public interface TraderLocalHome extends EJBLocalHome { public TraderLocal create() throws CreateException; }
5.Stateful Session Bean TraderBean.java
import javax.ejb.CreateException; import javax.ejb.RemoveException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; public class TraderBean implements SessionBean { static final boolean VERBOSE = true; private SessionContext ctx; private Context environment; private double tradingBalance; public void setSessionContext(SessionContext ctx) { log("setSessionContext called"); this.ctx = ctx; } public void ejbActivate() { log("ejbActivate called"); } public void ejbPassivate() { log("ejbPassivate called"); } public void ejbRemove() { log("ejbRemove called"); } public void ejbCreate() throws CreateException { log("ejbCreate called"); try { InitialContext ic = new InitialContext(); environment = (Context) ic.lookup("java:comp/env"); } catch (NamingException ne) { throw new CreateException("Could not look up context"); } this.tradingBalance = 0.0; } public TradeResult buy(String customerName, String stockSymbol, int shares) throws ProcessingErrorException { log("buy (" + customerName + ", " + stockSymbol + ", " + shares + ")"); double price = getStockPrice(stockSymbol); tradingBalance -= (shares * price); // subtract purchases from cash // account return new TradeResult(shares, price, TradeResult.BUY); } public TradeResult sell(String customerName, String stockSymbol, int shares) throws ProcessingErrorException { log("sell (" + customerName + ", " + stockSymbol + ", " + shares + ")"); double price = getStockPrice(stockSymbol); tradingBalance += (shares * price); return new TradeResult(shares, price, TradeResult.SELL); } public double getBalance() { return tradingBalance; } public double getStockPrice(String stockSymbol) throws ProcessingErrorException { try { return ((Double) environment.lookup(stockSymbol)).doubleValue(); } catch (NamingException ne) { throw new ProcessingErrorException("Stock symbol " + stockSymbol + " does not exist"); } catch (NumberFormatException nfe) { throw new ProcessingErrorException("Invalid price for stock " + stockSymbol); } } public double testLocal(){ Double balance=1.00; try{ InitialContext ic = new InitialContext(); TraderLocalHome localHome=(TraderLocalHome)ic.lookup("ejb/TraderEJB"); TraderLocal localTrader = (TraderLocal) localHome.create(); balance=localTrader.getBalance(); localTrader.remove(); }catch(Exception e){ log("local exception"); } return balance; } private void log(String s) { if (VERBOSE) { System.out.println(s); } } }
6.自定义Exception:ProcessingErrorException
public class ProcessingErrorException extends Exception { public ProcessingErrorException() {} public ProcessingErrorException(String message) {super(message);} }
7.Trade买卖结果封装的POJO:TradeResult
import java.io.Serializable; public final class TradeResult implements Serializable { public static final int SELL = 0; public static final int BUY = 1; private int numberTraded; // Number of shares really bought or sold private int action; // Whether shares were bought or sold private double price; // Price shares were bought or sold at public TradeResult(int numberTraded, double price, int action) { this.numberTraded = numberTraded; this.price = price; this.action = action; } public int getNumberTraded() { return numberTraded; } public int getActionTaken() { return action; } public double getPrice() { return price; } public String toString() { String result = numberTraded + " shares"; if(action == SELL) { result += "sold"; } else { result += "bought"; } result += " at a price of " + price; return result; } }
8.客户端调用EJB的程序:Client.java
import java.rmi.RemoteException; import java.util.Hashtable; import javax.ejb.CreateException; import javax.ejb.RemoveException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; public class Client { private static final String JNDI_NAME = "ejb20-statefulSession-TraderHome"; private String url; private TraderHome home; public Client(String url) { this.url = url; } public static void main(String[] args) throws Exception { log("\nBeginning statefulSession.Client...\n"); String url = "t3://localhost:7001"; Client client = null; // Parse the argument list if (args.length > 1) { log("Usage: java examples.ejb.ejb20.basic.statefulSession.Client t3://hostname:port"); return; } else if (args.length == 1) { url = args[0]; } try { client = new Client(url); client.example();// remote } catch (NamingException ne) { log("Unable to look up the beans home: " + ne.getMessage()); throw ne; } catch (Exception e) { log("There was an exception while creating and using the Trader."); log("This indicates that there was a problem communicating with the server: " + e); throw e; } log("\nEnd statefulSession.Client...\n"); } public void example() throws CreateException, ProcessingErrorException, RemoteException, RemoveException, NamingException { String customerName = "Matt"; // Create a Trader log("Creating trader\n"); home = lookupHome(); Trader trader = (Trader) narrow(home.create(), Trader.class); // Sell some stock String stockName = "MSFT"; int numberOfShares = 200; log("Selling " + numberOfShares + " of " + stockName); TradeResult tr = trader.sell(customerName, stockName, numberOfShares); log(tr.toString()); // Buy some stock stockName = "BEAS"; numberOfShares = 250; log("Buying " + numberOfShares + " of " + stockName); tr = trader.buy(customerName, stockName, numberOfShares); log(tr.toString()); // Get change in Cash Account from EJBean log("Change in Cash Account: $" + trader.getBalance() + "\n"); log("Local Ejb test start..."); log("testing localTrader balance is:" + trader.testLocal()); log("Local Ejb test end..."); log("Removing trader\n"); trader.remove(); } /** * RMI/IIOP clients should use this narrow function */ private Object narrow(Object ref, Class c) { return PortableRemoteObject.narrow(ref, c); } /** * Lookup the EJBs home in the JNDI tree */ private TraderHome lookupHome() throws NamingException { // Lookup the beans home using JNDI Context ctx = getInitialContext(); try { Object home = ctx.lookup(JNDI_NAME); return (TraderHome) narrow(home, TraderHome.class); } catch (NamingException ne) { log("The client was unable to lookup the EJBHome. Please make sure "); log("that you have deployed the ejb with the JNDI name " + JNDI_NAME + " on the WebLogic server at " + url); throw ne; } } /** * Using a Properties object will work on JDK 1.1.x and Java2 clients */ private Context getInitialContext() throws NamingException { try { // Get an InitialContext Hashtable<String, String> h = new Hashtable<String, String>(); h.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); h.put(Context.PROVIDER_URL, url); return new InitialContext(h); } catch (NamingException ne) { log("We were unable to get a connection to the WebLogic server at " + url); log("Please make sure that the server is running."); throw ne; } } private static void log(String s) { System.out.println(s); } }
9.ejb-jar.xml
<ejb-jar> <enterprise-beans> <session> <ejb-name>TraderEJB</ejb-name> <home>ejb.stateful.TraderHome</home> <remote>ejb.stateful.Trader</remote> <local-home>ejb.stateful.TraderLocalHome</local-home> <local>ejb.stateful.TraderLocal</local> <ejb-class>ejb.stateful.TraderBean</ejb-class> <session-type>Stateful</session-type> <transaction-type>Container</transaction-type> <env-entry> <env-entry-name>BEAS</env-entry-name> <env-entry-type>java.lang.Double</env-entry-type> <env-entry-value>100.00</env-entry-value> </env-entry> <env-entry> <env-entry-name>MSFT</env-entry-name> <env-entry-type>java.lang.Double</env-entry-type> <env-entry-value>150.00</env-entry-value> </env-entry> </session> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>TraderEJB</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar>
10.weblogic-ejb-jar.xml
<weblogic-ejb-jar> <weblogic-enterprise-bean> <ejb-name>TraderEJB</ejb-name> <stateful-session-descriptor/> <jndi-name>ejb20-statefulSession-TraderHome</jndi-name> <local-jndi-name>ejb/TraderEJB</local-jndi-name> </weblogic-enterprise-bean> </weblogic-ejb-jar>
11.run Client.java测试结果
Beginning statefulSession.Client... Creating trader Selling 200 of MSFT 200 sharessold at a price of 150.0 Buying 250 of BEAS 250 sharesbought at a price of 100.0 Change in Cash Account: $5000.0 Local Ejb test start... testing localTrader balance is:0.0 Local Ejb test end... Removing trader End statefulSession.Client...