EJB 3.0(Public Draft)入門記 Simplified API Chapter3 その2

前回うまくいかなかったローカルインタフェースを使用したEJBへのアクセスですが、根本的に勘違いしてたのでもういちどやり直します。

  • 登場人物はClientとShoppingCartBeanとCalculatorBean。
  • ShoppingCartBeanはリモートインタフェースを持っているステートフルセッションBean。
  • CalculatorBeanはローカルインタフェースを持っているステートレスセッションBean。(CalculatorにもCalculatorBeanにも@Localや@Remoteが指定されていませんが、Beanクラスが単一のインタフェースを実装している場合はそのインタフェースはデフォルトでローカルインタフェースになります。「3.2 Business Interfaces」より。)
  • Client → ShoppingCartBean → CalculatorBeanと呼び出します。(前回はClient → CalculatorBeanとしていて、EJBコンテナ外からローカルインタフェースを使用したEJBアクセスを行っていたためうまくいかないのでした。)

ソースコードはこんなカンジ。ほぼJBossのサンプルのパクリだったりします。

public interface Calculator {
  public int add(int x, int y);
  public int subtract(int x, int y);
}
@Stateless
public class CalculatorBean implements Calculator {
  public int add(int a, int b) {
    return a + b;
  }
  public int subtract(int a, int b) {
    return a - b;
  }
}
public interface ShoppingCart {
     void buy(String product, int quantity);
     HashMap getCartContents();
}
@Stateful
@Remote({ShoppingCart.class})
public class ShoppingCartBean implements ShoppingCart {

  private HashMap cart = new HashMap();

  public void buy(String product, int quantity) {
    if (cart.containsKey(product)) {
      int currq = cart.get(product);
      cart.put(product, getCalculator().add(currq, quantity));
    } else {
      cart.put(product, quantity);
    }
  }

  public HashMap getCartContents() {
    return cart;
  }

  private Calculator getCalculator() {
    try {
      InitialContext ctx = new InitialContext();
      return (Calculator) ctx.lookup(Calculator.class.getName());
    } catch (NamingException e) {
      throw new RuntimeException(e);
    }
  }
}
public class Client {
  public static void main(String[] args) throws Exception {
    InitialContext ctx = new InitialContext();
    ShoppingCart cart = (ShoppingCart) ctx.lookup(ShoppingCart.class.getName());
    cart.buy("おにぎり", 3);
    cart.buy("お茶", 2);
    cart.buy("おにぎり", 1);
    System.out.println(cart.getCartContents());
  }
}

ちなみに、ShoppingCartBeanがCalculatorを知るには@EJBアノテーションが使えるはずなのですが、とりあえず自分でlookupしてみました。

前回のbuild.xmlでデプロイしてClientを実行すると結果はこうなります。

{おにぎり=4, お茶=2}

成功です! あと、サーブレットからもCalculatorBeanが呼び出せました。

追記
コードが間違っていたので直しました。実はShoppingCartBeanがShoppingCartをimplementsしていなかったのです。でもこれはこれで動いていました。どうやら必ずしもインタフェースを実装していなくても@Remote({ShoppingCart.class})というアノテーションでビジネスインタフェースが示せれば動くようです、少なくともJBossでは。既存のEJBっぽいといえるのかな?