package ejbstrategy;
import javax.ejb.CreateException;
import java.rmi.RemoteException;
import javax.ejb.
EJBHome;
/**
* 渡されたStrategyを実行する
EJBのHome Interface
*/
public interface StrategyServerHome extends
EJBHome {
public StrategyServer create() throws CreateException, RemoteException;
}
package ejbstrategy;
import javax.ejb.
EJBObject;
import java.rmi.RemoteException;
/**
* 渡されたStrategyを実行する
EJBのRemote Interface
*/
public interface StrategyServer extends
EJBObject {
public void setStrategy(
EJBStrategy strategy) throws RemoteException;
public Object handleRequired(Event event) throws Exception, RemoteException;
public Object handleRequiresNew(Event event) throws Exception, RemoteException;
public Object handleMandatory(Event event) throws Exception, RemoteException;
public Object handleNotSupported(Event event) throws Exception, RemoteException;
public Object handleSupports(Event event) throws Exception, RemoteException;
public Object handleNever(Event event) throws Exception, RemoteException;
}
package ejbstrategy;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.CreateException;
/**
* 渡されたStrategyを実行する
EJB
*/
public class StrategyServerBean
implements SessionBean {
/** セッションコンテキスト */
private SessionContext context;
/** 処理を委譲するオブジェクト */
private
EJBStrategy strategy;
/**
* strategyに処理を委譲する。トランザクション属性がRequiredで実行される。
* @param event イベント名とパラメータ
* @exception Exception 例外
*/
public Object handleRequired(Event event) throws Exception {
return strategy.handleRequired(event);
}
/**
* strategyに処理を委譲する。トランザクション属性がRequiresNewで実行される。
* @param event イベント名とパラメータ
* @exception Exception 例外
*/
public Object handleRequiresNew(Event event) throws Exception {
return strategy.handleRequiresNew(event);
}
/**
* strategyに処理を委譲する。トランザクション属性がMandatoryで実行される。
* @param event イベント名とパラメータ
* @exception Exception 例外
*/
public Object handleMandatory(Event event) throws Exception {
return strategy.handleMandatory(event);
}
/**
* strategyに処理を委譲する。トランザクション属性がNotSupportedで実行される。
* @param event イベント名とパラメータ
* @exception Exception 例外
*/
public Object handleNotSupported(Event event) throws Exception {
return strategy.handleNotSupported(event);
}
/**
* strategyに処理を委譲する。トランザクション属性がSupportsで実行される。
* @param event イベント名とパラメータ
* @exception Exception 例外
*/
public Object handleSupports(Event event) throws Exception {
return strategy.handleSupports(event);
}
/**
* strategyに処理を委譲する。トランザクション属性がNeverで実行される。
* @param event イベント名とパラメータ
* @exception Exception 例外
*/
public Object handleNever(Event event) throws Exception {
return strategy.handleNever(event);
}
/**
* strategyを設定する。
* @param strategy 戦略(ロジック)
*/
public void setStrategy(
EJBStrategy strategy) {
this.strategy = strategy;
}
public void setSessionContext(SessionContext context) {
this.context = context;
}
public void ejbCreate() throws CreateException {}
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
}
package ejbstrategy;
import java.io.Serializable;
/**
* StrategyServerのhandle〜メソッド実行時に渡すオブジェクト
*/
public class Event implements Serializable {
/** イベント名 */
private String name;
/** データ */
private Object data;
public String getName() {
return name;
}
public Object getData() {
return data;
}
public void setName(String name) {
this.name = name;
}
public void setData(Object data) {
this.data = data;
}
}
package ejbstrategy;
import java.io.Serializable;
/**
* StrategyServerに渡すStrategyのインターフェース。
*/
public interface
EJBStrategy extends Serializable {
public Object handleRequired(Event event) throws Exception;
public Object handleRequiresNew(Event event) throws Exception;
public Object handleMandatory(Event event) throws Exception;
public Object handleNotSupported(Event event) throws Exception;
public Object handleSupports(Event event) throws Exception;
public Object handleNever(Event event) throws Exception;
}
package ejbstrategy;
/**
*
EJBStrategyの空実装クラス。
* このクラスを継承すれば実装したいhandle〜メソッドのみを
* 実装することが出来る。
*/
public abstract class
EJBStrategyAdapter implements EJBStrategy {
public Object handleRequired(Event event) throws Exception {
return null;
}
public Object handleRequiresNew(Event event) throws Exception {
return null;
}
public Object handleMandatory(Event event) throws Exception {
return null;
}
public Object handleNotSupported(Event event) throws Exception {
return null;
}
public Object handleSupports(Event event) throws Exception {
return null;
}
public Object handleNever(Event event) throws Exception {
return null;
}
}
package ejbstrategy;
import java.io.Serializable;
import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;
import javax.ejb.*;
/**
* StrategyServer
EJBの呼び出しをカプセル化する。(Business Delegate)
* lookup等のリモート呼び出しによる複雑さを隠蔽する。
*/
public class StrategyServerDelegate implements Serializable {
private transient StrategyServer bean;
private Handle handle;
public StrategyServerDelegate() {
try {
EJBHomeFactory factory = EJBHomeFactory.getInstance();
StrategyServerHome home = (StrategyServerHome)
factory.get
EJBHome("StrategyServer",
StrategyServerHome.class);
this.bean = home.create();
/*
* DelegateがSerializeされた時に復元する為に
EJB Handleを保持しておく。
*
EJBデザインパターンのサンプルに載っていた方法なのですが、
* うまく動きませんでした。なのでコメントアウトしてあります。
*/
//this.handle = this.bean.getHandle();
} catch (RemoteException ex) {
throw new RuntimeException(ex);
} catch (CreateException ex) {
throw new RuntimeException(ex);
}
}
public void remove() {
try {
get
EJB().remove();
} catch (RemoteException ex) {
throw new RuntimeException(ex);
} catch (RemoveException ex) {
throw new RuntimeException(ex);
}
}
private StrategyServer get
EJB() {
try {
if (this.bean == null) {
this.bean = (StrategyServer) PortableRemoteObject.narrow(
this.handle.get
EJBObject(), StrategyServer.class);
}
} catch (RemoteException ex) {
throw new RuntimeException(ex);
}
return this.bean;
}
public void setStrategy(
EJBStrategy strategy) {
try {
get
EJB().setStrategy(strategy);
} catch (RemoteException ex) {
throw new RuntimeException(ex);
}
}
public Object handleRequired(Event event) throws Exception {
return get
EJB().handleRequired(event);
}
public Object handleRequiresNew(Event event) throws Exception {
return get
EJB().handleRequiresNew(event);
}
public Object handleMandatory(Event event) throws Exception {
return get
EJB().handleMandatory(event);
}
public Object handleNotSupported(Event event) throws Exception {
return get
EJB().handleNotSupported(event);
}
public Object handleSupports(Event event) throws Exception {
return get
EJB().handleSupports(event);
}
public Object handleNever(Event event) throws Exception {
return get
EJB().handleNever(event);
}
}
package ejbstrategy;
import java.util.*;
import java.io.*;
import javax.ejb.*;
import javax.rmi.*;
import javax.naming.*;
public class
EJBHomeFactory {
/**
EJBHomeFactoryのインスタンス */
private static
EJBHomeFactory instance = new EJBHomeFactory();
/** コンテキスト */
private Context context;
/**
EJBHomeのリファレンスを保持 */
private Map homeMap = new HashMap();
/**
EJB名 */
private ResourceBundle bundle = ResourceBundle.getBundle("lookup");
/**
* コンストラクタ: コンテキストを初期化して保持する。
*/
private
EJBHomeFactory() {
try {
Properties prop = new Properties();
InputStream in = super.getClass().getResourceAsStream(
"/initialContext.properties");
prop.load(in);
context = new InitialContext(prop);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* コンストラクタ: サービスロケータを返す。
* @return サービスロケータ
*/
public static
EJBHomeFactory getInstance() {
return instance;
}
/**
*
EJBHome取得: EJBHomeを取得する。homeオブジェクトがすでに存在する場合、それを返す。
* @param ejbName
EJB名
* @param homeClass Homeクラス
* @return
EJBHome
*/
public synchronized
EJBHome getEJBHome(String ejbName, Class homeClass) {
EJBHome home = null;
try {
home = (
EJBHome) homeMap.get(homeClass);
if (home != null) {
return home;
}
Object objref = context.lookup(bundle.getString(ejbName));
home = (
EJBHome)PortableRemoteObject.narrow(objref, homeClass);
homeMap.put(homeClass, home);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return home;
}
}
package sample;
import ejbstrategy.*;
/**
* パターン説明の為のサンプルStrategy
*/
public class SampleStrategy extends
EJBStrategyAdapter {
public Object handleRequired(Event event) {
//DBを更新する等の処理をする。サンプルなので適当な値を返すだけ
Object result = (String) event.getData() + " executed update";
return result;
}
public Object handleSupports(Event event) {
//DBを読み込む等の処理をする。サンプルなので適当な値を返すだけ
Object result = (String) event.getData() + " executed load";
return result;
}
}
package sample;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import ejbstrategy.*;
/**
* パターン説明の為のサンプル
Servlet
*/
public class Sample
Servlet extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=Shift_JIS";
public void doGet(Http
ServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
Object result1 = null;
Object result2 = null;
try {
StrategyServerDelegate delegate = new StrategyServerDelegate();
SampleStrategy strategy = new SampleStrategy();
delegate.setStrategy(strategy);
Event event = new Event();
event.setData("sampledata1");
event.setName("doLoad");
result1 = delegate.handleSupports(event);
event.setData("sampledata2");
event.setName("doUpdate");
result2 = delegate.handleRequired(event);
} catch (Exception ex) {
throw new
ServletException(ex);
}
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Sample
Servlet</title></head>");
out.println("<body bgcolor=\"#ffffff\">");
out.println("result1=" + result1);
out.println("result2=" + result2);
out.println("</body></html>");
}
}
/*
ejb-jar.xmlも以下のように変更しました。
[ejb-jar.xml]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise[次行へ続く]
JavaBeans 2.0//EN' 'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>
<ejb-jar>
<display-name>StrategyServer</display-name>
<enterprise-beans>
<session>
<ejb-name>StrategyServer</ejb-name>
<home>ejbstrategy.StrategyServerHome</home>
<remote>ejbstrategy.StrategyServer</remote>
<ejb-class>ejbstrategy.StrategyServerBean</ejb-class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>StrategyServer</ejb-name>
<method-name>handleRequired</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>StrategyServer</ejb-name>
<method-name>handleRequiresNew</method-name>
</method>
<trans-attribute>RequiresNew</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>StrategyServer</ejb-name>
<method-name>handleMandatory</method-name>
</method>
<trans-attribute>Mandatory</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>StrategyServer</ejb-name>
<method-name>handleNotSupported</method-name>
</method>
<trans-attribute>NotSupported</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>StrategyServer</ejb-name>
<method-name>handleSupports</method-name>
</method>
<trans-attribute>Supports</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>StrategyServer</ejb-name>
<method-name>handleNever</method-name>
</method>
<trans-attribute>Never</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
トランザクション属性をhandle〜メソッドに〜と同じ属性を
設定してあります。
これにより、