270 likes | 425 Views
The order/customer example. Get the zip file with src dir http://javanotebook.com/2007/09/28/openejb_3_and_tomcat_6.html Buried down in this discussion is a link for a war file which includes the source. Download and unzip. Modify as per the following slides. Modifications.
E N D
Get the zip file with src dir • http://javanotebook.com/2007/09/28/openejb_3_and_tomcat_6.html • Buried down in this discussion is a link for a war file which includes the source. • Download and unzip. • Modify as per the following slides.
Modifications • The war file can be dropped into your webapps directory but will not run properly as currently configured. You will get a null pointer exception.
Customer • Lazy fetch means some fields – like persisted lists of things which have @OneToMany annotations - of a persisted ejb will not be fetched and this may cause a null pointer exception if you try to access them.
In Customer, orderlist should have fetch type eager package net.nycjava; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.persistence.*; //you’ll need to import persistence.* or specifically include the persistence.fetch @Entity @NamedQueries({ @NamedQuery(name = "Customer.findAll", query = "select o from Customer o"), @NamedQuery(name="Customer.findByEmail", query = "select o from Customer o where o.email = :email") }) @Table(name = "CUSTOMERS") public class Customer implements Serializable { @Id @Column(nullable = false) @GeneratedValue(strategy=GenerationType.SEQUENCE) private int id; private String email; ///////////////////////note change to next line @OneToMany(mappedBy = "customer", cascade=CascadeType.ALL,fetch=FetchType.EAGER) private List<Order> orderList;
javac/jar/classpath • An ant script would be best. I used a classpath batch file. • Something like this would work: set CLASSPATH=.;C:\...\ejb.jar;C:\...\jndi.jar;C:\...\geronimo-ejb.jar; C:\...\persistence.jar;C:\...\j2ee.jar;C:\ejb3example2\src; • You’ll have to include the actually full paths!!!
Javac and jar • Move down to src to compile, giving destination directory as the WEB-INF classes. • Move back up to jar (creating war) and put the war file in tomcat webapps. C:\ejb3example2>cd src C:\ejb3example2\src>javac net/nycjava/*.java -d ../WEB-INF/classes Note: net\nycjava\OrderManager.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. C:\ejb3example2\src>cd.. C:\ejb3example2>jar -cvf Customer.war WEB-INF added manifest adding: WEB-INF/(in = 0) (out= 0)(stored 0%) adding: WEB-INF/classes/(in = 0) (out= 0)(stored 0%) …..lots more here 46%) adding: WEB-INF/web.xml(in = 592) (out= 276)(deflated 53%) C:\ejb3example2>
Now it should run and show simulated customer and order info
What’s with that order #? • How come the order number stays 0? • You need to ask the manager to persist the order. • Add this line right before outputting the order info (around line 68): manager.persistEntity(order);
Named queries • You can create additional named queries for your classes. • For example, we should be able to search for all orders belonging to a given customer, because the customer is set as a field in the order. • This might be needed for monthly billing, or a customer may request this. • Below, I’ve added a second named query to customer. Note, you’ll need to import NamedQueries as well as NamedQuery //in Order @Entity @NamedQueries({ @NamedQuery(name = "Order.findAll", query = "select o from Order o"), @NamedQuery(name="Order.findByCustomerId", query = "select o from Order o where o.customer.id = :customerid") })
Getting it to work • Both the interfaces that the OrderManager implements, as well as the OrderManager itself, must now include this method. • The next slide shows how to add another query to the local interface. • You’ll need to add it to the remote interface as well.
OrderManagerLocal package net.nycjava; import javax.ejb.Local; import java.util.List; @Local public interface OrderManagerLocal { Object persistEntity(Object entity); Object mergeEntity(Object entity); List<Customer> queryCustomerFindAll(); List<Customer> queryCustomerFindByEmail(Object email); void removeCustomer(Customer customer); List<Order> queryOrderFindAll(); void removeOrder(Order order); List<OrderItem> queryOrderItemFindAll(); //add another List <Order> queryOrderFindByCustomerId(int c); void removeOrderItem(OrderItem item); List<Product> queryProductFindAll(); void removeProduct(Product item); }
Here’s the query in OrderManager • Add this query to the list in OrderManager public List<Order> queryOrderFindByCustomerId(int c) { return em.createNamedQuery("Order.findByCustomerId").setParameter("customerid",c).getResultList(); } • Check that everything still works
Using the new query • Ideally, we’d have a number of jsp or servlet functions: list all customers, list all products, list all orders, list orders by customers etc. • We’d probably like interfaces to provide CRUD for product and customer tables. • Let’s just add some output to show all orders for the given (simulated, randomly generated) customer.
Listing all orders for the current customer Customer Order Simulation: merged Customer:jane@herdomain order#4202 txid=TX1149498830 timestamp=2009-03-26 16:41:20.078 customer=jane@herdomain LineItems: product4 qty: 2 other orders for Customer: jane@herdomain order#301 txid=TX-1515117858 timestamp=2009-02-23 19:31:03.39 customer=jane@herdomain LineItems: product5 qty: 2 product2 qty: 2 order#2754 txid=TX1070503814 timestamp=2009-03-25 18:44:45.062 customer=jane@herdomain LineItems: product5 qty: 2 order#2764 txid=TX1070521423 timestamp=2009-03-25 18:45:02.671 customer=jane@herdomain LineItems: product1 qty: 1 product2 qty: 2 order#2851 txid=TX1070833205 timestamp=2009-03-25 18:50:14.453 customer=jane@herdomain LineItems: product2 qty: 2 order#3602 txid=TX1147072986 timestamp=2009-03-26 16:00:54.234 customer=jane@herdomain LineItems: product5 qty: 2 order#3907 txid=TX1149274236 timestamp=2009-03-26 16:37:35.484 customer=jane@herdomain LineItems: product1 qty: 2 product4 qty: 1 order#3908 txid=TX1149274236 timestamp=2009-03-26 16:37:35.484 customer=jane@herdomain LineItems: product1 qty: 2 product4 qty: 1 order#4201 txid=TX1149498830 timestamp=2009-03-26 16:41:20.078 customer=jane@herdomain LineItems: product4 qty: 2 order#4202 txid=TX1149498830 timestamp=2009-03-26 16:41:20.078 customer=jane@herdomain LineItems: product4 qty: 2
The mostly original servlet public class OrderServlet extends HttpServlet { @EJB private OrderManagerLocal manager; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = new PrintWriter(response.getOutputStream()); response.setContentType("text/plain"); //fill products method in last slide should be replaced List<Product> productlist= manager.queryProductFindAll(); if(productlist.isEmpty()) { productlist=fillProducts(); for(Product product:productlist) { manager.persistEntity(product); } } out.println("Customer Order Simulation:\n"); String emailAddress = generateEmailAddress(); List<Product> productsToBuy = generateProductsToBuy(productlist); Order order = new Order(); order.setDate(new Timestamp(System.currentTimeMillis())); order.setTransactionId(generateTransactionId()); List<OrderItem> lineItems = new ArrayList<OrderItem>(); for(Product product:productsToBuy) { OrderItem lineItem = new OrderItem(order); lineItem.setProduct(product); lineItem.setQuantity(new Random().nextInt(2)+1); lineItems.add(lineItem); } order.setOrderItemList(lineItems);
Servlet slide 2 Customer customer = getCustomer(emailAddress); if(customer==null) { customer= new Customer(); customer.setEmail(emailAddress); customer.addOrder(order); manager.persistEntity(customer); out.println("persisted Customer: "+customer.getEmail()); } else { customer.addOrder(order); customer=(Customer)manager.mergeEntity(customer); out.println("merged Customer:"+customer.getEmail()); } System.out.println("customer is "+customer.getId()); manager.persistEntity(order); out.println(order); //my added query & resultlist out.println("other orders for Customer: "+customer.getEmail()); List<Order> orders=manager.queryOrderFindByCustomerId(customer.getId()); for(int i=0;i<orders.size();i++) out.println(orders.get(i)); out.flush(); }
Servlet slide 3: product generation private List<Product> fillProducts() { List<Product> productList = new ArrayList<Product>(); for(int loop=1;loop<6;loop++) { Product product= new Product("product"+loop); productList.add(product); } return productList; } private String generateTransactionId() { return "TX"+(int)System.currentTimeMillis(); } private List<Product> generateProductsToBuy(List<Product> products) { int numProductsToBuy =2; if(products.size()<numProductsToBuy) numProductsToBuy=1; int numProducts = (new Random().nextInt(numProductsToBuy))+1; List<Product> productlist = new ArrayList<Product>(); for(int loop=0; loop<numProducts; loop++) { productlist.add(products.get(new Random().nextInt(products.size()))); } Set<Product> set = new HashSet<Product>(); // convert unique products to buy set.addAll(productlist); productlist.clear(); productlist.addAll(set); return productlist; }
Servlet slide 4: Customer generation for this simulation private String generateEmailAddress() {String[] emails = {"john@hisdomain", “mike@hisdomain", "jane@herdomain", "mary@herdomain", "me@mydomain", "you@yourdomain"}; return emails[new Random().nextInt(emails.length)]; } private Customer getCustomer(String emailAddress) { List<Customer> customers = manager.queryCustomerFindByEmail(emailAddress); if(customers.size()>0) { return customers.get(0); } return null; } }
What can you do with this? • Get it working as presented here. • Add more servlets to provide CRUD functionality to Products and Customers (Note the the getter/setter methods and many of the requisite queries – like remove – are already available) but currently customers are hard-coded fictitious email addresses and products are strings “product0”, “product1”, and so on. • Go back and redesign the customer and product classes. Product should have a part number, and cost. Customer should have a name (not just an email), and perhaps an address and phone number. • Provide a form/servlet for placing an order. • Add NamedQueries as needed.
ProductServlet: You’ll need to write manager.queryProductFindByName(name) package net.nycjava; //many imports public class ProductServlet extends HttpServlet { @EJB private OrderManagerLocal manager; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = new PrintWriter(response.getOutputStream()); response.setContentType("text/plain"); out.println("Product Editor Servlet:\n\tProducts\n\tName\tID"); List<Product> productlist= manager.queryProductFindAll(); for(int j=0;j<productlist.size();j++)out.println("\t"+productlist.get(j).getName()+"\t\t"+productlist.get(j).getId()); String name=request.getParameter("name"); String action =request.getParameter("action"); if(action.equals("delete")){ List<Product>xlist=manager.queryProductFindByName(name); if(xlist!=null&&xlist.size()>0) for(int j=0;j<xlist.size();j++)manager.removeProduct(xlist.get(j)); } else { Product p=new Product(name); manager.persistEntity(p);} out.println("Your changes have been processed\n\tProducts"); out.println("\n\tProducts\n\tName\tID"); productlist= manager.queryProductFindAll(); for(int j=0;j<productlist.size();j++)out.println("\t"+productlist.get(j).getName()+"\t\t"+productlist.get(j).getId()); out.flush(); }//get }//servlet