Server Components: Enterprise JavaBeans

Introdução aos Server Components

wpe8.jpg (19309 bytes)

n-tier.gif (23321 bytes)

Overview de Enterprise JavaBeans (EJB)

Programação Declarativa

Serviços Automáticos

Arquitetura

ejb1.gif (6860 bytes)

Novo Processo e Novos Papeis

ejb2.gif (12578 bytes)

Detalhes sobre o modelo EJB

Localização, Factory e Interfaces

ejb3.gif (13287 bytes)

Tipos de Beans

Característica

Session Bean

Entity Bean

O que o Bean  representa
  • Uma conversação transiente com um cliente
  • Pode ser considerado uma extensão do cliente que o criou
  • Pode acessar um banco de dados usando JDBC ou acessando um Entity Bean
  • Dão uma visão OO de um BD
  • Representam dados num banco de dados e os métodos que agem sobre os dados
  • Num SGBDR, cada Bean poderia  representar um registro de uma tabela, por exemplo
Tempo de vida
  • Igual ao tempo de vida do cliente. Existe somente durante uma sessão cliente/servidor
    (curto espaço de tempo)
  • Persiste tanto quanto os dados do banco de dados (longo espaço de tempo)
Atributos
  • Representam o estado da conversação. Este estado é mantido entre chamadas a métodos mas não depois que a sessão acaba
  • Representam dados de um banco de dados (colunas de uma tabela, por exemplo)
Persistência
(além da sessão)
  • O Bean deve gerenciar sua própria persistência
  • Gerenciada automaticamente pelo Container
Compartilhamento
  • Um único Bean por cliente (sem compartilhamento)
  • Acesso compartilhado entre clientes
  • Container gerencia a concorrência
Criação
  • No início de uma sessão
  • Identificado usando uma chave primária
  • A criação de um novo Bean insere dados num banco de dados
Durabilidade
  • Não sobrevive a um crash de servidor
  • Sobrevive a um crash de servidor
Transação
  • Pode ser "transaction-aware", se assim for programado
  • Transacional
Exemplo
  • Shopping Cart
  • User Account Bean mantendo os dados associados a um usuário num site de compras

Diferenças entre dois tipos de Session Beans

Característica

Stateful Session Bean

Stateless Session Bean

Gerência de estado
  • Gerenciado automaticamente pelo Container
    (Activation, Passivation)
  • Não há estado a ser gerenciado
  • Bean pode sair da memória sem salvar qualquer coisa (não há "Passivation")
  • Beans são intercambiáveis e podem ser alocados de um "pool"
Responsabilidades
  • Estado conversacional pode ser mantido no Bean
  • O cliente tem que manter qualquer estado necessário
Performance
  • Mais pesado
  • Extremamente lightweight
Exemplo
  • Shopping Cart
  • Verificação de crédito
    (Todo o trabalho pode ser feito numa única chamada de método)
  • Mailer Bean para enviar mail confirmando uma compra
  • Bean que valida um ID de empregado
  • Acesso a um Catálogo de Produtos. Embora pareça melhor usar um Entity bean aqui, dedido à persistência, lembre que o catálogo não está associado a um cliente particular e que nenhum estado sobre o cliente deve ser mantido. Porém, um estado geral, não específico a um cliente particular pode ser mantido. Podemos usar Stateless Beans para montar uma cache do catálogo à medida que este é acessado. O Bean provê browsing e searching no catálogo. Como o Bean poderá manipular várias linhas do catálogo ao mesmo tempo (no search, p. ex.) e oferecer uma visão compartilhada de informação, o Bean poderá ser compartilhado.

Regras para escolher o tipo de Bean

Detalhes sobre os serviços automáticos

Gerência de estado

Gerência de persistência

ejb4.gif (22270 bytes)

Gerência de transações

Segurança

Detalhes adicionais sobre o Container

Um exemplo de aplicação com EJB

Descrição do Problema

Um pouco de análise

manu1.gif (9561 bytes)

Criar um produto

Fazer um pedido

Cancelar um pedido

Selecionar um pedido para manufatura

Fabricar um produto

Despachar um pedido

Listar pedidos atrasados

Alguns detalhes iniciais de implementação

Ator Tipo de interface com usuário Implementação do objeto de interface
Engenheiro Visual Basic Session Bean (RMI/IIOP)
Cliente Web Aplicação Web/JSPs JavaBean proxy/Session Bean
Operador de telefone GUI Swing Session Bean
Gerente de chão Aplicação Web/JSPs JavaBean proxy/Session Bean
Membro de equipe de manufatura Palm Pilot com WAP/WML Servlet acessando Session Bean
Gerente Aplicação Web/JSPs JavaBean proxy/Session Bean

A Implementação dos Clientes e das Interfaces de Lógica do Negócio

package factory.manage_orders;

import javax.ejb.*;

public interface ManageOrdersHome extends EJBHome
{
  ManageOrders create() throws java.rmi.RemoteException, 
                               javax.ejb.CreateException;
}
package factory.manage_orders;

import javax.ejb.*;
import java.util.Date;
import java.rmi.RemoteException;
import factory.order.OrderNotCancelableException;

public interface ManageOrders extends EJBObject
{
  void placeOrder(int salesDivision, int orderNumber,
                  String product, Date dateDue)
       throws RemoteException, NoSuchProductException,
              DuplicateOrderException;

  void cancelOrder(int salesDivision, int orderNumber)
       throws RemoteException, NoSuchOrderException,
              OrderNotCancelableException;

  OverdueOrderView[] getOverdueOrders() throws RemoteException;

  OpenOrderView[] getSchedulableOrders() throws RemoteException;

  void createSampleProducts() throws RemoteException;

  void createProduct(String id, String name) throws RemoteException;

  void addRoutingInstruction(String id, int sequence, String instruction)
       throws RemoteException;
}
package factory.manage_orders;

public class DuplicateOrderException extends Exception {
  public DuplicateOrderException() {
  }
}

package factory.manage_orders;

public class NoSuchOrderException extends Exception {

  public NoSuchOrderException() {
  }
}

package factory.manage_orders;

public class NoSuchProductException extends Exception {

  public NoSuchProductException() {
  }
}
package factory.manage_orders;

import java.io.Serializable;
import java.util.Date;

public class OpenOrderView implements Serializable {
  public final int salesDivision;
  public final int orderNumber;
  public final String product;
  public final Date dateDue;

  public OpenOrderView(int salesDivision, int orderNumber,
                       String product, Date dateDue ) {
    this.salesDivision = salesDivision;
    this.orderNumber = orderNumber;
    this.product = product;
    this.dateDue = dateDue;
  }
}

package factory.manage_orders;

import java.io.Serializable;
import java.util.Date;

public class OverdueOrderView implements Serializable {
  public final int salesDivision;
  public final int orderNumber;
  public final String product;
  public final String status;
  public final Date dateDue;

  public OverdueOrderView(int salesDivision, int orderNumber,
                          String product, String status, Date dateDue) {
    this.salesDivision = salesDivision;
    this.orderNumber = orderNumber;
    this.product = product;
    this.status = status;
    this.dateDue = dateDue;
  }
}
package factory.manufacture;

import javax.ejb.*;
import java.rmi.RemoteException;

public interface ManufactureHome extends EJBHome {
  Manufacture create(String manufactureCellID)
              throws RemoteException, CreateException;
}
package factory.manufacture;

import javax.ejb.*;
import java.rmi.RemoteException;
import factory.manage_orders.OpenOrderView;
import factory.manage_orders.NoSuchOrderException;

public interface Manufacture extends EJBObject {
  OpenOrderView[] getOpenOrders() throws RemoteException;

  void selectForManufacture(int salesDivision, int order_number)
       throws RemoteException, NoSuchOrderException, BadStatusException;

  boolean hasNextRouting() throws RemoteException, NoSelectionException;

  String getNextRouting() throws RemoteException, NoSelectionException;

  void ship(String carrier, int loading_dock) 
       throws RemoteException, NoSelectionException; 
}
package factory.clients;

import java.rmi.RemoteException;
import javax.ejb.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import java.util.Properties;

import factory.manage_orders.ManageOrders;
import factory.manage_orders.ManageOrdersHome;

public class CreateProducts {
  public static void main(String[] args)   {
    try {
      ContextPropertiesFactory factory = new ContextPropertiesFactory();
      Properties prop = factory.getInitialContextProperties();
      InitialContext initial = new InitialContext(prop);
      //InitialContext initial = new InitialContext();

      Object homeObject = initial.lookup("ManageOrders");

      ManageOrdersHome home = (ManageOrdersHome)
            PortableRemoteObject.narrow(homeObject, ManageOrdersHome.class);

      ManageOrders manageOrders = home.create();

      manageOrders.createSampleProducts();
    } catch(RemoteException re) {
      re.printStackTrace();
    } catch(NamingException ne) {
      ne.printStackTrace();
    } catch(CreateException ce) {
      ce.printStackTrace();
    }
  }
}
package factory.clients;

import javax.naming.Context;
import java.util.Properties;

public class ContextPropertiesFactory {
  public Properties getInitialContextProperties() {
    Properties prop = new Properties();
    prop.setProperty(Context.INITIAL_CONTEXT_FACTORY,
         "com.evermind.server.ApplicationClientInitialContextFactory");
    prop.setProperty(Context.PROVIDER_URL, "ormi://localhost/factory");
    prop.setProperty(Context.SECURITY_PRINCIPAL, "admin");
    prop.setProperty(Context.SECURITY_CREDENTIALS, "123");
    return prop;
  }

  public void makePropertiesDefault() {
    System.setProperties( getInitialContextProperties() );
  }
}
package factory.clients;

import java.rmi.RemoteException;
import javax.ejb.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import java.util.Properties;
import java.util.Calendar;
import java.util.Date;

import factory.manage_orders.ManageOrders;
import factory.manage_orders.ManageOrdersHome;

public class PlaceSampleOrders {
  private static final int SALES_DIVISION_1 = 1;
  private static final int SALES_DIVISION_2 = 2;
  private static final int SALES_DIVISION_3 = 3;

  private static final int ORDER_1 = 1;
  private static final int ORDER_2 = 2;
  private static final int ORDER_3 = 3;
  private static final int ORDER_4 = 4;
  private static final int ORDER_5 = 5;

  private static final String PRODUCT_1 = "DESK01";
  private static final String PRODUCT_2 = "CHAIR01";
  private static final String PRODUCT_3 = "LAMP01";

  public static void main(String[] args) {
    try {
      ContextPropertiesFactory factory = new ContextPropertiesFactory();
      Properties prop = factory.getInitialContextProperties();
      InitialContext initial = new InitialContext(prop);
      //InitialContext initial = new InitialContext();

      Object homeObject = initial.lookup("ManageOrders");

      ManageOrdersHome home = (ManageOrdersHome)
        PortableRemoteObject.narrow(homeObject, ManageOrdersHome.class);

      ManageOrders manageOrders = home.create();

      Calendar calendarNotSchedulable = Calendar.getInstance();
      calendarNotSchedulable.add(Calendar.DAY_OF_YEAR, 14);

      Calendar calendarSchedulable = Calendar.getInstance();
      calendarSchedulable.add(Calendar.DAY_OF_YEAR, 5);

      Calendar calendarOverdue = Calendar.getInstance();

      manageOrders.placeOrder(SALES_DIVISION_1, ORDER_1, PRODUCT_1, 
                              calendarNotSchedulable.getTime());

      manageOrders.placeOrder(SALES_DIVISION_2, ORDER_1, PRODUCT_2, 
                              calendarNotSchedulable.getTime());

      manageOrders.placeOrder(SALES_DIVISION_1, ORDER_2, PRODUCT_3, 
                              calendarSchedulable.getTime());

      manageOrders.placeOrder(SALES_DIVISION_2, ORDER_2, PRODUCT_1, 
                              calendarSchedulable.getTime());

      manageOrders.placeOrder(SALES_DIVISION_1, ORDER_3, PRODUCT_2, 
                              calendarOverdue.getTime());

      manageOrders.placeOrder(SALES_DIVISION_2, ORDER_3, PRODUCT_3, 
                              calendarOverdue.getTime());

    } catch(Exception e) {
      e.printStackTrace();
    }
  }
}
package factory.clients;

import java.rmi.RemoteException;
import javax.ejb.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import java.util.Properties;

import factory.manage_orders.ManageOrders;
import factory.manage_orders.ManageOrdersHome;
import factory.manage_orders.OverdueOrderView;
import factory.manage_orders.OpenOrderView;

public class ManageSampleOrders {
  public static void main(String[] args) {
    try {
      ContextPropertiesFactory factory = new ContextPropertiesFactory();
      Properties prop = factory.getInitialContextProperties();
      InitialContext initial = new InitialContext( prop );

      Object homeObject = initial.lookup("ManageOrders");

      ManageOrdersHome home = (ManageOrdersHome)
        PortableRemoteObject.narrow(homeObject, ManageOrdersHome.class);

      ManageOrders manageOrders = home.create();

      // List overdue orders
      OverdueOrderView[] overdueOrders = manageOrders.getOverdueOrders();
      for(int iter = 0; iter < overdueOrders.length; iter++) {
        OverdueOrderView overdueOrder = overdueOrders[iter];
        System.out.println("Product " + overdueOrder.product + 
                           " is due on " + overdueOrder.dateDue + 
                           ".  It's status is " + overdueOrder.status 
                           + ".");
      }

      // Cancel first overdue order
      if(overdueOrders.length > 0) {
        OverdueOrderView overdueOrder = overdueOrders[0];
        System.out.println("About to cancel an order...");
        try {
          manageOrders.cancelOrder(overdueOrder.salesDivision, 
                                   overdueOrder.orderNumber );
          System.out.println("Canceled order for " + 
                             overdueOrder.product.trim() + ".");
        } catch(factory.manage_orders.NoSuchOrderException nsoe) {
          System.out.println("Failed to find order.");
        } catch(factory.order.OrderNotCancelableException once) {
          System.out.println("Cannot cancel an order in production.");
        }
      }
    } catch(RemoteException re) {
      re.printStackTrace();
    } catch(NamingException ne) {
      ne.printStackTrace();
    } catch(CreateException ce) {
      ce.printStackTrace();
    }
  }
}
public class BeginManufacture {
  private static final String MANUFACTURE_CELL = "Station1";
  ...

      ContextPropertiesFactory factory = new ContextPropertiesFactory();
      Properties prop = factory.getInitialContextProperties();
      InitialContext initial = new InitialContext(prop);

      Object homeObject = initial.lookup("Manufacture");

      ManufactureHome home = (ManufactureHome)
        PortableRemoteObject.narrow(homeObject, ManufactureHome.class);

      Manufacture manufacture = home.create(MANUFACTURE_CELL);
  ...
// primeiro, alguém salva um handle para um session bean existente
  private static final String FILE_NAME = "C:/current_product.ser";
  ...
          Handle handle = manufacture.getHandle();
          FileOutputStream file_out = new FileOutputStream(FILE_NAME);
          ObjectOutputStream out = new ObjectOutputStream(file_out);
          out.writeObject(handle);
          System.out.println("Written object for next stage.");
...

// em outro programa, obtém-se o handle de volta
      FileInputStream inStream = new FileInputStream(FILE_NAME);
      ObjectInputStream in = new ObjectInputStream(inStream);
      Handle handle = (Handle) in.readObject();
      Manufacture manufacture = (Manufacture)
                  PortableRemoteObject.narrow(handle.getEJBObject(), 
                  Manufacture.class);
package factory.clients;

import java.rmi.RemoteException;
import javax.ejb.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import java.util.Properties;
import java.io.*;

import factory.manufacture.Manufacture;
import factory.manufacture.ManufactureHome;
import factory.manage_orders.OpenOrderView;

public class BeginManufacture {
  private static final String MANUFACTURE_CELL = "Station1";
  private static final String FILE_NAME = "C:/current_product.ser";

  public static void main(String[] args) {
    try {
      ContextPropertiesFactory factory = new ContextPropertiesFactory();
      Properties prop = factory.getInitialContextProperties();
      InitialContext initial = new InitialContext(prop);

      Object homeObject = initial.lookup("Manufacture");

      ManufactureHome home = (ManufactureHome)
        PortableRemoteObject.narrow(homeObject, ManufactureHome.class);

      Manufacture manufacture = home.create(MANUFACTURE_CELL);
      OpenOrderView[] openOrders = manufacture.getOpenOrders();

      if(openOrders.length == 0) {
        System.out.println("Nothing to make; go home.");
        return;
      }

      System.out.println("Selecting from the following open orders:");
      for(int iter = 0; iter < openOrders.length; iter++) {
        OpenOrderView openOrder = openOrders[iter];
        System.out.println("Sales Division: " + openOrder.salesDivision +
                           "; Order #: " + openOrder.orderNumber + 
						   "; Product: " + openOrder.product + "Date due: " 
                           + openOrder.dateDue );
      }

      // Get the first open order
      for (int iterFind = 0; iterFind < openOrders.length; iterFind++) {
        try {
          OpenOrderView openOrder = openOrders[iterFind];
          manufacture.selectForManufacture(
                     openOrder.salesDivision, openOrder.orderNumber);
          Handle handle = manufacture.getHandle();
          FileOutputStream file_out = new FileOutputStream(FILE_NAME);
          ObjectOutputStream out = new ObjectOutputStream(file_out);
          out.writeObject(handle);
          System.out.println("Written object for next stage.");
          break;
        } catch(factory.manufacture.BadStatusException bse) {
          // Someone grabbed it before we did
          bse.printStackTrace();
        }
      }
    } catch (FileNotFoundException fnfe) {
      fnfe.printStackTrace();
    } catch (RemoteException re) {
      re.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    } catch (factory.manage_orders.NoSuchOrderException nsoe) {
      nsoe.printStackTrace();
    } catch (NamingException ne) {
      ne.printStackTrace();
    } catch (CreateException ce) {
      ce.printStackTrace();
    }
  }
}
package factory.clients;

import java.rmi.RemoteException;
import javax.ejb.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import java.util.Properties;
import java.io.*;

import factory.manufacture.Manufacture;
import factory.manufacture.ManufactureHome;
import factory.manage_orders.OpenOrderView;

public class CompleteManufacture {
  private static final String FILE_NAME = "c:/current_product.ser";
  private static final String CARRIER = "State Express";
  private static final int LOADING_DOCK = 1;

  public static void main(String[] args) {
    try {
      ContextPropertiesFactory factory = new ContextPropertiesFactory();
      factory.makePropertiesDefault();

      FileInputStream inStream = new FileInputStream(FILE_NAME);
      ObjectInputStream in = new ObjectInputStream(inStream);
      Handle handle = (Handle) in.readObject();
      Manufacture manufacture = (Manufacture)
                  PortableRemoteObject.narrow(handle.getEJBObject(), 
                                              Manufacture.class);
      System.out.println("Product routings:");

      while(manufacture.hasNextRouting()) {
        String routing = manufacture.getNextRouting();
        System.out.println(routing);
      }
      System.out.println("Product finished; shipping...");
      manufacture.ship(CARRIER, LOADING_DOCK);
      manufacture.remove();
    } catch(Exception e) {
      e.printStackTrace();
    } catch(Throwable t) {
      t.printStackTrace();
    }
  }
}

A Implementação do Session Bean sem Estado

Business methods

package factory.manage_orders;

import javax.ejb.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import factory.order.OrderHome;
import factory.order.Order;
import factory.order.OrderPK;
import factory.order.StatusStrings;
import factory.product.Product;
import factory.product.ProductHome;
import factory.product.RoutingInstruction;
import factory.order.OrderNotCancelableException;

public class ManageOrdersEJB implements SessionBean
{
  private static final int MILLIS_IN_DAYS = 86400000;

  // Business methods

  public void placeOrder(int salesDivision, int orderNumber,
                         String productName, Date dateDue)
              throws NoSuchProductException, DuplicateOrderException  {
    try {
      // Find the product
      ProductHome productHome = getProductHome();
      Product product = productHome.findByPrimaryKey(productName);
      // create the order
      OrderHome orderHome = getOrderHome();
      orderHome.create(salesDivision, orderNumber, product, dateDue);
    }
    catch(NamingException ne) {
      throw new EJBException(ne);
    } catch(RemoteException re) {
      throw new EJBException(re);
    } catch (FinderException fe) {
      if(fe instanceof ObjectNotFoundException)
         throw new NoSuchProductException();
      else
         throw new EJBException(fe); // Erro de sistema, não da aplicação
    } catch(CreateException ce) {
      if(orderExists(salesDivision, orderNumber))
         throw new DuplicateOrderException();
      else
         throw new EJBException(ce);
    }
  }

  public void cancelOrder(int salesDivision, int orderNumber)
              throws NoSuchOrderException, OrderNotCancelableException {
    try {
      // Find the order
      OrderHome orderHome = getOrderHome();
      OrderPK orderPK = new OrderPK(salesDivision, orderNumber);

      // Cancel it
      Order order = orderHome.findByPrimaryKey(orderPK);
      order.cancelOrder();
    } catch(NamingException ne) {
      throw new EJBException(ne);
    } catch(RemoteException re) {
      throw new EJBException(re);
    } catch(FinderException fe) {
      if(fe instanceof ObjectNotFoundException)
         throw new NoSuchOrderException();
      else
         throw new EJBException(fe);
    }
  }

  public OverdueOrderView[] getOverdueOrders() {
    try {
      LinkedList overdueOrders = new LinkedList();
      Date today = new Date();
      long todayMillis = today.getTime();
      long leadTimeMillis = getLeadTimeDays() * MILLIS_IN_DAYS;
      OrderHome orderHome = getOrderHome();
      Collection uncompletedOrders = orderHome.findUncompletedOrders();
      Iterator iterUncompletedOrders = uncompletedOrders.iterator();
      while(iterUncompletedOrders.hasNext()) {
        Order uncompletedOrder = (Order)
              PortableRemoteObject.narrow(iterUncompletedOrders.next(),
                                          Order.class);
        Date dateDue = uncompletedOrder.getDateDue();
        String status = uncompletedOrder.getStatus();
        long dueDateMillis = dateDue.getTime();
        if(
           (status.equals(StatusStrings.OPEN) &&
              (todayMillis + leadTimeMillis > dueDateMillis))
                ||
            (status.equals(StatusStrings.IN_PROCESS) &&
              (todayMillis > dueDateMillis))
          ) {
          OverdueOrderView view = new OverdueOrderView(
                           uncompletedOrder.getSalesDivision(),
                           uncompletedOrder.getOrderNumber(),
                           uncompletedOrder.getProductOrdered().getName(),
                           status, dateDue);
          overdueOrders.add(view);
        }
      }
      OverdueOrderView[] overdue = new OverdueOrderView[  
                                       overdueOrders.size()];
      return (OverdueOrderView[]) overdueOrders.toArray(overdue);
    } catch(NamingException ne) {
      throw new EJBException(ne);
    } catch(RemoteException re) {
      throw new EJBException(re);
    } catch(FinderException fe) {
      throw new EJBException(fe);
    }
  }

  public OpenOrderView[] getSchedulableOrders() {
    try {
      LinkedList schedulableOrders = new LinkedList();
      Date today = new Date();
      long todayMillis = today.getTime();
      long maxInventoryTimeMillis = getMaxInventoryTimeDays() * 
                                    MILLIS_IN_DAYS;
      long leadTimeMillis = getLeadTimeDays() * MILLIS_IN_DAYS;
      OrderHome orderHome = getOrderHome();
      Collection openOrders = orderHome.findOpenOrders();
      Iterator iterOpenOrders = openOrders.iterator();
      while(iterOpenOrders.hasNext()) {
        Order openOrder = (Order)
          PortableRemoteObject.narrow(iterOpenOrders.next(),
                                      Order.class);
        Date dateDue = openOrder.getDateDue();
        long dueDateMillis = dateDue.getTime();
        if(todayMillis >= dueDateMillis - leadTimeMillis - maxInventoryTimeMillis) {
          OpenOrderView view = new OpenOrderView(
                        openOrder.getSalesDivision(),
                        openOrder.getOrderNumber(),
                        openOrder.getProductOrdered().getName(),
                        dateDue);
          schedulableOrders.add(view);
        }
      }
      OpenOrderView[] schedulable =
                      new OpenOrderView[schedulableOrders.size()];
      return (OpenOrderView[]) schedulableOrders.toArray(schedulable);
    } catch(NamingException ne) {
      throw new EJBException(ne);
    } catch(RemoteException re) {
      throw new EJBException(re);
    } catch(FinderException fe) {
      throw new EJBException(fe);
    }
  }

  public void createSampleProducts() {
    try {
      ProductHome productHome = getProductHome();
      // Create three sample products
      ProductCreationHelper pch = new ProductCreationHelper(productHome);
      pch.createAll();
    } catch(NamingException ne) {
      throw new EJBException(ne);
    }
  }

  public void createProduct(String id, String name) {
    try {
      ProductHome productHome = getProductHome();
      productHome.create(id, name, new RoutingInstruction[]{});
    } catch(NamingException ne) {
      throw new EJBException(ne);
    } catch(CreateException ce) {
      throw new EJBException(ce);
    } catch (RemoteException re) {
      throw new EJBException(re);
    }
  }

  public void addRoutingInstruction(String id, int sequence,
                                    String instruction) {
    try {
      ProductHome productHome = getProductHome();
      Product product = productHome.findByPrimaryKey(id);
      product.addRoutingInstruction(sequence, instruction);
    } catch(FinderException fe) {
      throw new EJBException(fe);
    } catch(NamingException ne) {
      throw new EJBException(ne);
    } catch(RemoteException re) {
      throw new EJBException(re);
    }
  }
package factory.manage_orders;

import javax.ejb.EJBException;
import factory.product.Product;
import factory.product.ProductHome;
import factory.product.RoutingInstruction;
import factory.product.NoSuchRoutingInstruction;

public class ProductCreationHelper {
  ProductHome productHome;

  public ProductCreationHelper(ProductHome productHome) {
    this.productHome = productHome;
  }

  public void createAll() {
    try {
      createDesk();
      createChair();
      createLamp();
    } catch(Exception e) {
      e.printStackTrace();
      throw new EJBException(e);
    }
  }

  public void createDesk() throws Exception {
    RoutingInstruction compress = new RoutingInstruction(5, 
                                      "Compress the wood.");
    RoutingInstruction stain = new RoutingInstruction(10, 
                                   "Stain the wood.");
    RoutingInstruction assemble = new RoutingInstruction(15, 
                                      "Assemble the desk.");
    RoutingInstruction[] routings = new RoutingInstruction[]{
                                        compress, stain, assemble};

    productHome.create("DESK01", "Compressed Wood Desk", routings);
  }

  public void createChair() throws Exception {
    RoutingInstruction extrude = new RoutingInstruction(5, 
                                     "Extrude plastic.");
    RoutingInstruction glue = new RoutingInstruction(10, 
                                  "Glue together.");
    RoutingInstruction paint = new RoutingInstruction(15, 
                                   "Spraypaint.");
    RoutingInstruction[] routings = new RoutingInstruction[]{
                                        extrude, glue, paint};

    productHome.create("CHAIR01", "Quality Plastic Chair", routings);
  }

  public void createLamp() throws Exception {
    RoutingInstruction getBulb = new RoutingInstruction(5, 
                                     "Get bulb from inventory.");
    RoutingInstruction getLamp = new RoutingInstruction(10, 
                                     "Get lamp from inventory.");
    RoutingInstruction screwTogether = new RoutingInstruction(15, 
                                           "Screw together.");
    RoutingInstruction frayCord = new RoutingInstruction(20, 
                                      "Pre-fray the cord");
    RoutingInstruction[] routings = new RoutingInstruction[]{
                                        getBulb, getLamp, screwTogether, 
                                        frayCord};

    Product lamp = productHome.create("LAMP01", "Custom Made Lamp", 
                                       routings);
    try {
      lamp.deleteRoutingInstruction(21);
    } catch(NoSuchRoutingInstruction nsri) {
      lamp.deleteRoutingInstruction(20);
    }
  }
}

 

Os helper methods

  private boolean orderExists(int salesDivision, int orderNumber) {
    try {
      OrderHome orderHome = getOrderHome();
      OrderPK orderPK = new OrderPK(salesDivision, orderNumber);
      Order order = orderHome.findByPrimaryKey(orderPK);
      return true;
    } catch(Exception e) {
      return false;
    }
  }

  private int getLeadTimeDays() throws NamingException {
    InitialContext initial = new InitialContext();
    Integer leadTimeDays = (Integer) 
                           initial.lookup("java:comp/env/lead_time");
    // A null pointer will roll back the transaction
    return leadTimeDays.intValue();
  }

  private int getMaxInventoryTimeDays() throws NamingException {
    InitialContext initial = new InitialContext();
    Integer inventoryTimeDays = (Integer)initial.lookup(
                                "java:comp/env/max_inventory_time");
    // A null pointer will roll back the transaction
    return inventoryTimeDays.intValue();
  }

  private ProductHome getProductHome() throws NamingException {
    InitialContext initial = new InitialContext();
    ProductHome home = (ProductHome)
                javax.rmi.PortableRemoteObject.narrow(
                          initial.lookup("java:comp/env/ejb/Product"), 
                                         ProductHome.class );
    return home;
  }

  private OrderHome getOrderHome() throws NamingException {
    InitialContext initial = new InitialContext();
    OrderHome home = (OrderHome)javax.rmi.PortableRemoteObject.narrow(
                                initial.lookup("java:comp/env/ejb/Order"), 
                                               OrderHome.class );
    return home;
  }
      <env-entry>
        <env-entry-name>lead_time</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>3</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>max_inventory_time</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>10</env-entry-value>
      </env-entry>
      <ejb-ref>
        <ejb-ref-name>ejb/Order</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>factory.order.OrderHome</home>
        <remote>factory.order.Order</remote>
        <ejb-link>Orders</ejb-link>
      </ejb-ref>
      <ejb-ref>
        <ejb-ref-name>ejb/Product</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>factory.product.ProductHome</home>
        <remote>factory.product.Product</remote>
        <ejb-link>Product</ejb-link>
      </ejb-ref>

Lifecycle e framework methods

  public void ejbCreate() {}

  public void ejbActivate() {}

  public void ejbPassivate() {}

  public void ejbRemove() {}

  public void setSessionContext(SessionContext ctx) {}
} // fim da classe ManageOrdersEJB

A Implementação do Session Bean com Estado

package factory.manufacture;

import javax.ejb.*;
import javax.naming.*;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.List;
import java.util.Collections;
import java.util.Iterator;
import java.util.Date;
import factory.product.Product;
import factory.product.ProductHome;
import factory.order.Order;
import factory.order.OrderHome;
import factory.order.OrderPK;
import factory.order.StatusStrings;
import factory.manage_orders.OpenOrderView;
import factory.manage_orders.ManageOrders;
import factory.manage_orders.ManageOrdersHome;
import factory.manage_orders.NoSuchOrderException;
import factory.product.RoutingInstruction;

public class ManufactureEJB implements SessionBean {
  // properties
  public String manufactureCellID;
  public List routingInstructions;
  public int currentPosition;
  public int lastPosition;

  public boolean orderSelected;
  public int selectedSalesDivision;
  public int selectedOrderNumber;

// Framework & lifecycle methods

  public void ejbCreate(String manufactureCellID) {
    this.manufactureCellID = manufactureCellID;
    orderSelected = false;
  }

  public void ejbActivate() {}

  public void ejbPassivate() {}

  public void ejbRemove() {}

  public void setSessionContext(SessionContext ctx) {}

// Business methods

  public OpenOrderView[] getOpenOrders() {
    try {
      ManageOrdersHome homeManageOrders = getManageOrdersHome();
      ManageOrders manageOrders = homeManageOrders.create();
      return manageOrders.getSchedulableOrders();
    } catch(NamingException ne) {
      throw new EJBException(ne);
    } catch(RemoteException re) {
      throw new EJBException(re);
    } catch(CreateException ce) {
      throw new EJBException(ce);
    }
  }

  public void selectForManufacture(int salesDivision, int order_number)
              throws NoSuchOrderException, BadStatusException {
    try {
      OrderHome homeOrder = getOrderHome();
      OrderPK orderPK = new OrderPK(salesDivision, order_number);
      Order order = homeOrder.findByPrimaryKey(orderPK);
      String orderStatus = order.getStatus();
      if(!orderStatus.equals(StatusStrings.OPEN))
         throw new BadStatusException(orderStatus);
      order.beginManufacture();
      Product product = order.getProductOrdered();
      RoutingInstruction[] productRouting =
                           product.getRoutingInstructions();
      routingInstructions = Arrays.asList(productRouting);
      Collections.sort(routingInstructions);
      currentPosition = 0;
      lastPosition = routingInstructions.size() - 1;
      selectedSalesDivision = salesDivision;
      selectedOrderNumber = order_number;
      orderSelected = true;
    } catch(NamingException ne) {
      ne.printStackTrace();
      throw new EJBException(ne);
    } catch(RemoteException re) {
      re.printStackTrace();
      throw new EJBException(re);
    } catch(FinderException fe) {
      fe.printStackTrace();
      if(fe instanceof ObjectNotFoundException)
         throw new NoSuchOrderException();
      else
         throw new EJBException(fe);
    }
  }

  public boolean hasNextRouting() throws NoSelectionException {
    if(!orderSelected)
       throw new NoSelectionException();
    return (currentPosition <= lastPosition);
  }

  public String getNextRouting() throws NoSelectionException {
    if(!orderSelected)
       throw new NoSelectionException();

    RoutingInstruction ri = (RoutingInstruction)
                            routingInstructions.get( currentPosition++ );
    return ri.instruction;
  }

  public void ship(String carrier, int loading_dock)
              throws NoSelectionException {
    // Sales division, order number, carrier,
    // loading dock, date completed, manufactured by

    if(!orderSelected)
       throw new NoSelectionException();

    Connection con = null;

    try {
      con = getConnection();
      PreparedStatement statement = con.prepareStatement(
                                        getShipmentSQLString());
      statement.setInt(1, selectedSalesDivision);
      statement.setInt(2, selectedOrderNumber);
      statement.setString(3, carrier);
      statement.setInt(4, loading_dock);
      statement.setDate(5, new java.sql.Date((new Date()).getTime()));
      statement.setString(6, manufactureCellID);
      statement.executeUpdate();
      statement.close();
      con.close();
      orderSelected = false;

      OrderHome homeOrder = getOrderHome();
      OrderPK orderPK = new OrderPK(
                            selectedSalesDivision, selectedOrderNumber);
      Order order = homeOrder.findByPrimaryKey(orderPK);
      order.completeManufacture();
    } catch(NamingException ne) {
      ne.printStackTrace();
      throw new EJBException(ne);
    } catch(SQLException sqle) {
      try {
        if(con != null)
          con.close();
      } catch (Exception e){}
      sqle.printStackTrace();
      throw new EJBException(sqle);
    } catch(RemoteException re) {
      throw new EJBException(re);
    } catch(FinderException fe) {
      throw new EJBException(fe);
    }
  }
  private String getShipmentSQLString() throws NamingException {
    InitialContext initial = new InitialContext();
    String sql = (String) initial.lookup("java:comp/env/shipmentSQL");
    return sql;
  }
}
      <env-entry>
        <env-entry-name>shipmentSQL</env-entry-name>
        <env-entry-type>java.lang.String</env-entry-type>
        <env-entry-value>insert into shipments (division, order_number, carrier, loading_dock, date_completed, manufactured_by ) values (?, ?, ?, ?, ?, ?)</env-entry-value>
      </env-entry>
CREATE TABLE SHIPMENTS (DIVISION INTEGER NOT NULL,
                        ORDER_NUMBER INTEGER NOT NULL,
                        CARRIER CHAR(50),
                        LOADING_DOCK INTEGER,
                        DATA_COMPLETED DATE,
                        MANUFACTURED_BY CHAR(50),
                        PRIMARY KEY (DIVISION, ORDER_NUMBER));
  private OrderHome getOrderHome() throws NamingException {
    InitialContext initial = new InitialContext();
    OrderHome home = (OrderHome)javax.rmi.PortableRemoteObject.narrow(
                      initial.lookup("java:comp/env/ejb/Order"), 
                                     OrderHome.class );
    return home;
  }

  private ManageOrdersHome getManageOrdersHome() throws NamingException {
    InitialContext initial = new InitialContext();
    ManageOrdersHome home = (ManageOrdersHome)  
                             javax.rmi.PortableRemoteObject.narrow(
                             initial.lookup(
                                    "java:comp/env/ejb/ManageOrders"),  
                                    ManageOrdersHome.class );
    return home;
  }

  private Connection getConnection() throws SQLException, NamingException {
    Context initial = new InitialContext();
    DataSource dataSource =
              (DataSource)initial.lookup("java:comp/env/jdbc/shipDB");
    return dataSource.getConnection();
  }

  private String getShipmentSQLString() throws NamingException {
    InitialContext initial = new InitialContext();
    String sql = (String) initial.lookup("java:comp/env/shipmentSQL");
    return sql;
  }
}
      <resource-ref>
        <res-ref-name>jdbc/shipDB</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
      </resource-ref>

A Implementação dos Entity Beans

O Bean Order

package factory.order;

import javax.ejb.*;
import javax.naming.*;
import java.rmi.RemoteException;
import factory.product.Product;
import factory.product.ProductHome;
import java.util.Date;

public class OrderEJB implements EntityBean {
  // properties
  private static final String OPEN_STATUS = "o";
  private static final String DEFAULT_STATUS = OPEN_STATUS;
  private static final String CANCELED_STATUS = "c";
  private static final String IN_PROCESS_STATUS = "m";
  private static final String COMPLETED_STATUS = "f";

  public int salesDivision;
  public int orderNumber;
  public Product productOrdered;
  public String status;
  public Date dateDue;
package factory.order;

import java.io.Serializable;

public class OrderPK implements Serializable {
  public int salesDivision;
  public int orderNumber;

  // mandatory empty constructor
  public OrderPK() {}

  // convenience constructor
  public OrderPK( int salesDivision, int orderNumber ) {
    this.salesDivision = salesDivision;
    this.orderNumber = orderNumber;
  }
}
package factory.order;

import javax.ejb.*;
import java.rmi.RemoteException;
import java.util.Date;
import factory.product.Product;

public interface Order extends EJBObject {
  public int getSalesDivision()
    throws RemoteException;

  public int getOrderNumber()
    throws RemoteException;

  public Product getProductOrdered()
    throws RemoteException;

  public String getStatus()
    throws RemoteException;

  public void cancelOrder()
    throws RemoteException, OrderNotCancelableException;

  public void beginManufacture()
    throws RemoteException;

  public void completeManufacture()
    throws RemoteException;

  public Date getDateDue()
    throws RemoteException;
}
  // business methods

  public int getSalesDivision() {
    return salesDivision;
  }

  public int getOrderNumber() {
    return orderNumber;
  }

  public Product getProductOrdered() {
    return productOrdered;
  }

  public String getStatus() {
    if (status.equals( OPEN_STATUS ))
      return StatusStrings.OPEN;
    else if (status.equals( CANCELED_STATUS ))
      return StatusStrings.CANCELED;
    else if (status.equals( IN_PROCESS_STATUS ))
      return StatusStrings.IN_PROCESS;
    else if (status.equals( COMPLETED_STATUS ))
      return StatusStrings.COMPLETED;
    throw new EJBException( "Unknown status" );
  }

  public void cancelOrder()
    throws OrderNotCancelableException {
    if (
      status.equals( IN_PROCESS_STATUS )
        ||
      status.equals( COMPLETED_STATUS )
        )
      throw new OrderNotCancelableException();
    status = CANCELED_STATUS;
  }

  public void beginManufacture() {
    status = IN_PROCESS_STATUS;
  }

  public void completeManufacture() {
    status = COMPLETED_STATUS;
  }

  public Date getDateDue() {
    return dateDue;
  }
package factory.order;

public class StatusStrings {
  public static final String OPEN = "open";
  public static final String CANCELED = "canceled";
  public static final String IN_PROCESS = "in process";
  public static final String COMPLETED = "completed";
}
  public void ejbLoad() {
    status = status.trim();
  }

  public void ejbPassivate() {}

  public void ejbRemove() {}

  public void ejbStore() {}

  public void setEntityContext(EntityContext ctx) {}

  public void unsetEntityContext() {}
  // lifecycle and framework methods

  public OrderPK ejbCreate( int salesDivision, int orderNumber,
    Product productOrdered, Date dateDue )
    throws CreateException
  {
    this.salesDivision = salesDivision;
    this.orderNumber = orderNumber;
    this.productOrdered = productOrdered;
    this.dateDue = dateDue;
    status = DEFAULT_STATUS;

    return null; // for container-managed persistence
  }

  public void ejbPostCreate( int salesDivision, int orderNumber,
    Product productOrdered, Date dateDue ) {}

  public OrderPK ejbCreate( int salesDivision, int orderNumber,
    String product, Date dateDue )
    throws CreateException
  {
    this.salesDivision = salesDivision;
    this.orderNumber = orderNumber;
    this.dateDue = dateDue;
    status = DEFAULT_STATUS;

    try {
      ProductHome productHome = getProductHome();
      this.productOrdered = productHome.findByPrimaryKey( product );
    } catch (RemoteException re) {
      re.printStackTrace();
      throw new EJBException( re );
    } catch (FinderException fe) {
      fe.printStackTrace();
      throw new CreateException( "Product does not exist" );
    }
    return null; // for container-managed persistence
  }

  public void ejbPostCreate( int salesDivision, int orderNumber,
    String product, Date dateDue )
  {
  }

  // implementation helpers

  private ProductHome getProductHome() {
    try {
      InitialContext initial = new InitialContext();
      ProductHome home = (ProductHome) javax.rmi.PortableRemoteObject.narrow(
        initial.lookup( "java:comp/env/ejb/Product" ), ProductHome.class );
      return home;
    } catch (NamingException ne) {
      ne.printStackTrace();
      throw new EJBException( ne );
    }
  }
package factory.order;

import javax.ejb.*;
import java.rmi.RemoteException;
import factory.product.Product;
import java.util.Date;
import java.util.Collection;

public interface OrderHome extends EJBHome {
  Order create(  int salesDivision, int orderNumber,
    Product productOrdered, Date dateDue )
    throws RemoteException, CreateException;

  Order create(  int salesDivision, int orderNumber,
    String productOrdered, Date dateDue )
    throws RemoteException, CreateException;

  Order findByPrimaryKey( OrderPK order )
    throws RemoteException, FinderException;

  Collection findOpenOrders()
    throws RemoteException, FinderException;

  Collection findUncompletedOrders()
    throws RemoteException, FinderException;
}
<finder-method query="$status starting with 'o'">
  <method>
    <ejb-name>Orders</ejb-name>
    <method-name>findOpenOrders</method-name>
    <method-params>
    </method-params>
  </method>
</finder-method>
<finder-method query="$status not starting with 'c' and
                      $status not starting with 'f'">
  <method>
    <ejb-name>Orders</ejb-name>
    <method-name>findUncompletedOrders</method-name>
    <method-params>
    </method-params>
  </method>
</finder-method>
<query>
  <query-method>
    <method-name>findOpenOrders</method-name>
    <method-params/>
  </query-method>
  <ejb-sql>WHERE status LIKE 'o%'</ejb-sql>
</query>

<query>
  <query-method>
    <method-name>findUncompletedOrders</method-name>
    <method-params/>
  </query-method>
  <ejb-sql>WHERE status NOT LIKE 'c%' AND status NOT LIKE 'f%'</ejb-sql>
</query>

O Bean Product

package factory.product;

import java.io.Serializable;


public class RoutingInstruction implements Serializable, Comparable {
  public int sequence;
  public String instruction;

  public RoutingInstruction() {
  }

  public RoutingInstruction( int sequence, String instruction ) {
    this.sequence = sequence;
    this.instruction = instruction;
  }

  public int compareTo(Object o) {
    RoutingInstruction ri = (RoutingInstruction) o;
    if (sequence < ri.sequence)
      return -1;
    else if (sequence == ri.sequence)
      return 0;
    else
      return 1;
  }
} 
package factory.product;

import javax.ejb.*;
import java.util.List;
import java.util.LinkedList;
import java.util.Arrays;
import java.util.Iterator;

public class ProductEJB implements EntityBean {

  // properties

  public String product;
  public String name;
  public List routingInstructions;
package factory.product;

import javax.ejb.*;
import java.rmi.RemoteException;

public interface Product extends EJBObject {
  public String getProduct()
    throws RemoteException;

  public String getName()
    throws RemoteException;

  public void setName( String name )
    throws RemoteException;

  public RoutingInstruction[] getRoutingInstructions()
    throws RemoteException;

  public void addRoutingInstruction( int sequence, String instruction )
    throws RemoteException;

  public void deleteRoutingInstruction( int sequence )
    throws RemoteException, NoSuchRoutingInstruction;

  public void replaceRoutingInstructions(
    RoutingInstruction[] newRoutingInstructions )
    throws RemoteException;
}
  // business methods

  public String getProduct() {
    return product;
  }

  public String getName() {
    return name;
  }

  public void setName( String name ) {
    this.name = name;
  }

  public RoutingInstruction[] getRoutingInstructions() {
    RoutingInstruction[] routingArray =
      new RoutingInstruction[ routingInstructions.size() ];
    return (RoutingInstruction[]) routingInstructions.toArray( routingArray );
  }

  public void addRoutingInstruction( int sequence, String instruction ) {
    routingInstructions.add( new RoutingInstruction( sequence, instruction) );
  }

  public void deleteRoutingInstruction( int sequence )
    throws NoSuchRoutingInstruction
  {
    Iterator iter = routingInstructions.iterator();
    while (iter.hasNext()) {
      RoutingInstruction ri = (RoutingInstruction) iter.next();
      if (ri.sequence == sequence) {
        iter.remove();
        return;
      }
    }
    throw new NoSuchRoutingInstruction();
  }

  public void replaceRoutingInstructions(
    RoutingInstruction[] newRoutingInstructions )
  {
    routingInstructions.clear();
    routingInstructions.addAll(
      Arrays.asList( newRoutingInstructions ) );
  }
  // framework and life-cycle methods

  public String ejbCreate( String product, String name,
    RoutingInstruction[] routingInstructions ) {
    this.product = product;
    this.name = name;
    this.routingInstructions = new LinkedList();
    this.routingInstructions.addAll(
      Arrays.asList( routingInstructions ) );
    return null;
  }

  public void ejbPostCreate( String product, String name,
    RoutingInstruction[] routingInstructions ) {
  }

  public void ejbActivate() {}

  public void ejbLoad() {}

  public void ejbPassivate() {}

  public void ejbRemove() {}

  public void ejbStore() {}

  public void setEntityContext(EntityContext ctx) {}

  public void unsetEntityContext() {}
} 
package book.product;

import javax.ejb.*;
import java.rmi.RemoteException;

public interface ProductHome extends EJBHome {
  Product create( String product, String name,
    RoutingInstruction[] routingInstructions )
    throws RemoteException, CreateException;

  Product findByPrimaryKey( String product )
    throws RemoteException, FinderException;
}

O Deployment Descriptor Final

<?xml version="1.0"?>

<ejb-jar>
 <enterprise-beans>
   <session>
      <ejb-name>ManageOrders</ejb-name>
      <home>factory.manage_orders.ManageOrdersHome</home>
      <remote>factory.manage_orders.ManageOrders</remote>
      <ejb-class>factory.manage_orders.ManageOrdersEJB</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
      <ejb-ref>
        <ejb-ref-name>ejb/Order</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>factory.order.OrderHome</home>
        <remote>factory.order.Order</remote>
        <ejb-link>Orders</ejb-link>
      </ejb-ref>
      <ejb-ref>
        <ejb-ref-name>ejb/Product</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>factory.product.ProductHome</home>
        <remote>factory.product.Product</remote>
        <ejb-link>Product</ejb-link>
      </ejb-ref>
      <env-entry>
        <env-entry-name>lead_time</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>3</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>max_inventory_time</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>10</env-entry-value>
      </env-entry>
   </session>
    <session>
      <ejb-name>Manufacture</ejb-name>
      <home>factory.manufacture.ManufactureHome</home>
      <remote>factory.manufacture.Manufacture</remote>
      <ejb-class>factory.manufacture.ManufactureEJB</ejb-class>
      <session-type>Stateful</session-type>
      <transaction-type>Container</transaction-type>
      <ejb-ref>
        <ejb-ref-name>ejb/Order</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>factory.order.OrderHome</home>
        <remote>factory.order.Order</remote>
        <ejb-link>Orders</ejb-link>
      </ejb-ref>
      <ejb-ref>
        <ejb-ref-name>ejb/ManageOrders</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <home>factory.manage_orders.ManageOrdersHome</home>
        <remote>factory.manage_orders.ManageOrders</remote>
        <ejb-link>ManageOrders</ejb-link>
      </ejb-ref>
      <env-entry>
        <env-entry-name>shipmentSQL</env-entry-name>
        <env-entry-type>java.lang.String</env-entry-type>
        <env-entry-value>insert into shipments (division, order_number, carrier, loading_dock, date_completed, manufactured_by ) values (?, ?, ?, ?, ?, ?)</env-entry-value>
      </env-entry>
      <resource-ref>
        <res-ref-name>jdbc/shipDB</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
      </resource-ref>
   </session>
   <entity>
      <ejb-name>Orders</ejb-name>
      <home>factory.order.OrderHome</home>
      <remote>factory.order.Order</remote>
      <ejb-class>factory.order.OrderEJB</ejb-class>
            <prim-key-class>factory.order.OrderPK</prim-key-class>
            <reentrant>False</reentrant>
            <persistence-type>Container</persistence-type>
            <cmp-field><field-name>salesDivision</field-name></cmp-field>
            <cmp-field><field-name>orderNumber</field-name></cmp-field>
            <cmp-field><field-name>productOrdered</field-name></cmp-field>
            <cmp-field><field-name>status</field-name></cmp-field>
            <cmp-field><field-name>dateDue</field-name></cmp-field>
      <ejb-ref>
        <ejb-ref-name>ejb/Product</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>factory.product.ProductHome</home>
        <remote>factory.product.Product</remote>
        <ejb-link>Product</ejb-link>
      </ejb-ref>
   </entity>
   <entity>
      <ejb-name>Product</ejb-name>
      <home>factory.product.ProductHome</home>
      <remote>factory.product.Product</remote>
      <ejb-class>factory.product.ProductEJB</ejb-class>
           <prim-key-class>java.lang.String</prim-key-class>
           <primkey-field>product</primkey-field>
           <reentrant>False</reentrant>
           <persistence-type>Container</persistence-type>
           <cmp-field><field-name>product</field-name></cmp-field>
           <cmp-field><field-name>name</field-name></cmp-field>
           <cmp-field><field-name>routingInstructions</field-name>
           </cmp-field>
   </entity>

 </enterprise-beans>
 <assembly-descriptor>
   <container-transaction>
     <method>
        <ejb-name>Orders</ejb-name>
        <method-name>*</method-name>
     </method>
     <trans-attribute>Required</trans-attribute>
   </container-transaction>
   <container-transaction>
     <method>
        <ejb-name>Product</ejb-name>
        <method-name>*</method-name>
     </method>
     <trans-attribute>Required</trans-attribute>
   </container-transaction>
   <container-transaction>
     <method>
        <ejb-name>ManageOrders</ejb-name>
        <method-name>*</method-name>
     </method>
     <trans-attribute>Required</trans-attribute>
   </container-transaction>
   <container-transaction>
     <method>
        <ejb-name>Manufacture</ejb-name>
        <method-name>*</method-name>
     </method>
     <trans-attribute>Required</trans-attribute>
   </container-transaction>
 </assembly-descriptor>
</ejb-jar>

Execução da Aplicação Final

Comparação de JavaBeans e EJB

JavaBeans

Enterprise JavaBeans

JavaBeans podem ser visíveis ou não em tempo de execução Um EJB é um objeto remoto não visual
JavaBeans rodam num único processo e foram feitos basicamente para rodar no cliente

É possível usar JavaBeans no servidor (como proxy bean para acessar EJB, por exemplo)

EJBs são componentes executáveis remotamente e só podem executar no servidor
Com JavaBeans, eventos são fundamentais: são a base da interconexão de componentes Eventos não são importantes em EJB. Outras propriedades (persistência, concorrência, segurança, etc.) são importantes

Não há relação entre os dois modelos de componentes

JavaBeans têm uma interface externa (Properties) que permite que uma ferramenta interprete a funcionalidade do Bean EJBs têm um Deployment Descriptor que descreve sua funcionalidade, ou pelo menos que parametriza parte do comportamento desejado que o Container tem que implementar
JavaBeans podem ter classe BeanInfo, Property Editors, ou Customizers. EJBs não têm esses conceitos e só possuem o Deployment Descriptor
Não há tipos diferentes de JavaBeans Tem dois tipos de EJBs: Entity e Session
Há um bridge disponível para implantar um Bean como controle ActiveX Não se pode transformar um EJB num controle ActiveX, embora seja possível usar VB como cliente para acessar EJBs
Para ser usado como server component, o programador teria que escrever muita funcionalidade adicional O framework já foi escrito

Produtos

comp-4 programa anterior próxima