Опубликован: 18.03.2010 | Доступ: свободный | Студентов: 840 / 85 | Оценка: 4.48 / 4.33 | Длительность: 12:01:00
Лекция 3:

Технология Enterprise Java Beans. Часть 1

Тестовый клиент для ShoppingBasketBean

Тестовый клиент для компонента ShoppingBasketBean создает один экземпляр компонента и делает тестовый заказ.

public class TestClient2   
{
public static void main(String args[])   
	{
	try 
		{
		Context jndiContext = createJBossContext();
		Object ref = jndiContext.lookup("ShoppingBasketBean"); 
		ShoppingBasketHome home = (ShoppingBasketHome) PortableRemoteObject.narrow(ref, ShoppingBasketHome.class);
		ShoppingBasketRemote remote = home.create("Boris");
		System.out.println("Starting to work with the shop");
		remote.addCommodity(2);
		remote.addCommodity(3);
		remote.addCommodity(4);
		
		remote.processOrder(); 
		}   
	catch   (RemoteException e)   
		{
		e.printStackTrace(); 
		}   
	catch   (NamingException e)   
		{
		e.printStackTrace(); 
		}   
	catch   (CreateException e)   
		{
		e.printStackTrace(); 
		}   
	catch   (SQLException e)   
		{
		e.printStackTrace();
		}
	}
	
public static Context createJBossContext()   throws NamingException  
	{
	Properties p = new Properties(); 
	p.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); 
	p.put("java.naming.provider.url", "jnp://127.0.0.1:1099"); 
	p.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces"); 
	Context jndiContext = new InitialContext(p); 
	return jndiContext;
	}
}

В консоль данный тестовый клиент ничего не выводит, но можно посмотреть результат его работы, выполнив два запроса в базе данных в SQL*PLUS:

  • select * from ORDERS;
  • select * from COMMODITY_ORDER.
Новый заказ добавлен

Рис. 3.40. Новый заказ добавлен

Результаты выполнения запросов показаны на Рис. 3.40. Как видно, в таблице ORDERS появилась информация о новом заказе, а в таблице COMMODITYORDERS - информация о составе заказа.

Дескрипторы развертывания

Дескрипторы развертывания определены для трех компонентов в одном файле ejb-jar.xml. Дескрипторы сеансовых компонентов без состояния CommoditiesListBean и OrdersListBean ничем не отличаются от дескрипторов развертывания компонентов из предыдущих примеров. У компонента ShoppingBasketBean в элементе session-type будет стоять вместо Stateless- Stateful.

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar ID" version="2.1"
xmlns = "http://java.sun.com/xml/ns/j2ee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">

<description>Beans  for the Shopping Basket</description>

<display-name>ShoppingBasketBean</display-name>
<enterprise-beans> <session>
<ejb-name>CommoditiesListBean</ejb-name> 
<home>shoppingBasket.CommoditiesListHome</home> 
<remote>shoppingBasket.CommoditiesListRemote</remote> 
<ejb-class>shoppingBasket.CommoditiesListBean</ejb-class> 
<session-type>Stateless</session-type> 
<transaction-type>Container</transaction-type> 
</session>
<session>
<ejb-name>OrdersListBean</ejb-name>
<home>shoppingBasket.OrdersListHome</home>
<remote>shoppingBasket.OrdersListRemote</remote>
<ejb-class>shoppingBasket.OrdersListBean</ejb-class> 
<session-type>Stateless</session-type> 
<transaction-type>Container</transaction-type> 
</session>
<session>
<ejb-name>ShoppingBasketBean</ejb-name> 
<home>shoppingBasket.ShoppingBasketHome</home> 
<remote>shoppingBasket.ShoppingBasketRemote</remote> 
<ejb-class>shoppingBasket.ShoppingBasketBean</ejb-class> 
<session-type>Stateful</session-type> 
<transaction-type>Container</transaction-type> 
</session> </enterprise-beans> 
</ejb-jar>
Клиентское приложение

В этом примере в качестве клиентского приложения будет выступать веб-приложение, написанное при помощи сервлетов и JSP.В данном пособии не ставиться цель научить с нуля программировать на сервлетах и JSP. Поэтому предполагается, что некоторые знания по этой теме у читателя уже есть.

Логика работы данного веб-приложения будет заключаться в следующем: пользователю отображается некоторая веб-страница, генерируемая при помощи JSP.После чего пользователь с этой веб-страницы может перейти на другую веб-страницу, либо послать данные на обработку некоторому сервлету (либо при помощи формы, либо просто посредством ссылки). Компоненты EJB хранятся в контексте JSP -сессии (Session).Помимо этого в контексте сессии хранится имя пользователя, под которым он вошел в систему. Для любого веб-магазина характерны следующие страницы:

  • Страница входа. Здесь пользователь вводит свое имя и пароль. В этом примере в качестве этой страницы будет использоваться страница index.jsp.
  • Страница со списком товаров для покупки. Здесь пользователь может выбрать среди списка всего доступного в магазине что-нибудь себе по вкусу. В примере это goodlist.jsp.
  • Страница с корзиной. Здесь отображается текущее состояние корзины. Пользователь может пересчитать количество товаров в корзине или вообще удалить какой-то или какие-то товары из корзины. В примере это basket.jsp.
  • Страница "Спасибо за покупку". Отображается, когда клиент сделал заказ. Предлагает посетить магазин еще раз. В примере это thankyou.jsp.
  • Страница с информацией о предыдущих заказах. Здесь пользователь может узнать когда и какие заказы он уже делал в этом магазине. В примере это prevorders.jsp.

Помимо страниц, необходимы еще сервлеты, которые будут обрабатывать действия пользователя. Сервлеты необходимы для:

  • Добавления товара в корзину, сервлет AddToCartServlet.
  • Пересчета товаров в корзине, сервлет RecalculateServlet.
  • Выполнения заказа, сервлет MakeOrderServlet.
  • Входа в систему, сервлет LoginServlet.
  • Выхода из системы, сервлет LogoutServlet.

Помимо сервлетов, будет использоваться фильтр сервлетов. Если пользователь не вошел в магазин, этот фильтр будет перенаправлять его на страницу входа index.jsp, в случае если он вдруг попытается запросить какую-либо другую страницу или сервлет. Фильтр называется AuthFilter.

Рассмотрим страницу входа в магазин.

<%@ page language="java" contentType="text/html;   charset=cp1251"
pageEncoding="cp1251"%>
<%String username = (String) session.getAttribute("username");
// Пользователь уже вошел в магазин - отправляем его на страницу
// со списком товаров
if (username != null) {
application.getRequestDispatcher("/goodlist.jsp").forward(request, response);
}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;   charset=cp1251">
<title>Login</title>
</head>
<body>
// Данные отправляются сервлету LoginServlet. В URL-адресах ему поставлен 
// в соответствие адрес,   заканчивающийся на login.
// Стоит отметить,  что мы не используем пароли для пользователей. 
// Каждый волен входить под тем именем, которое ему нравится.
<form action="login" method="post"> <table>
<tr>
<td> Login:
</td> <td>
<input type="text" name="username"></input>
</td>
</tr> <tr>
<td>
<input type="SUBMIT" value="Login"></input> </td>
</tr> </table> </form>
</body>
</html>
Страница входа в систему

Рис. 3.41. Страница входа в систему

Страница входа в систему показана на Рис. 3.41.

Теперь рассмотрим сервлет входа в систему. Он обрабатывает только Р0SТ -запросы. Данный сервлет, получив данные формы, сохраняет имя пользователя в контексте сессии. Затем он получает удаленные интерфейсы трех ЕJB -компонентов и также сохраняет их в контексте сессии. Теперь они будут доступны на всех остальных страницах в магазине.

public class LoginServlet extends HttpServlet  
{ 
private Context jndiContext = null;
private static final long serialVersionUID = 4562488849398632419L;
public LoginServlet()   
	{
	super();
	try 
		{
		jndiContext = createJBossContext(); 
		}   
	catch (NamingException e)   
		{
		e.printStackTrace();
		}
	}

private static Context createJBossContext()   throws NamingException  
	{
	Properties p = new Properties();
	p.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
	p.put("java.naming.provider.url",   "jnp://127.0.0.1:1099");
	p.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
	Context jndiContext = new InitialContext(p);
	return jndiContext;
	}

protected void doPost(HttpServletRequest req,  HttpServletResponse res)   
	{ 
	String loginName = req.getParameter("username"); 
	HttpSession session = req.getSession();
	
	// Если пользователь еще не вошел в магазин
	if (session.getAttribute("username") == null)   
		{
		// Сохраняем имя пользователя в контексте сессии 
		session.setAttribute("username",   loginName);
		Object ref;
		try 
			{
			// Получаем и сохраняем три удаленных интерфейса 
			// компонентов EJB в сессии.
			ref = jndiContext.lookup("ShoppingBasketBean"); 
			ShoppingBasketHome home =   (ShoppingBasketHome) PortableRemoteObject.narrow
				(ref, ShoppingBasketHome.class); 
			ShoppingBasketRemote remote = home.create(loginName); 
			session.setAttribute("basketbean",   remote);
			
			ref = jndiContext.lookup("CommoditiesListBean"); 
			CommoditiesListHome homeCom =   (CommoditiesListHome) 
				PortableRemoteObject.narrow(ref, CommoditiesListHome.class); 
			CommoditiesListRemote remoteCom = homeCom.create();
			
			session.setAttribute("commoditiesbean",   remoteCom);
			
			ref = jndiContext.lookup("OrdersListBean");
			OrdersListHome homeOrd =   (OrdersListHome)
			PortableRemoteObject.narrow(ref, OrdersListHome.class);
			OrdersListRemote remoteOrd = homeOrd.create();
			session.setAttribute("ordersbean",   remoteOrd); 
			}   
		catch   (NamingException e)   
			{
			e.printStackTrace(); 
			}   
		catch   (CreateException e)   
			{
			e.printStackTrace(); 
			}   
		catch   (RemoteException e)   
			{
			e.printStackTrace();
			}
		}
	
	// Отправляем пользователя на страницу с товарами 
	RequestDispatcher reqDispatcher = getServletContext().getRequestDispatcher("/goodlist.jsp");
	try 
		{
		reqDispatcher.forward(req,   res); 
		}   
	catch   (java.io.IOException e)   
		{
		e.printStackTrace(); 
		}   
	catch   (javax.servlet.ServletException e)   
		{
		e.printStackTrace();
		}
	}
}

Перейдем к странице с товарами. Здесь вся логика сводится к получению компонента CommoditiesListBean из контекста сессии, и отображения доступных товаров. Для каждого товара определена ссылка на сервлет добавления товара AddToCartServlet.В таблице COMMODITIESLIST у каждого объекта было определено такое поле как IMAGEPATH - в нем хранится путь до изображения, которое соответствует товару. При помощи Google&trade; находим фотографии различных пачек сигарет и поместим их в каталог img.

<%@ page language="java" contentType="text/html; 
	charset=cp1251" pageEncoding="cp1251"%>
<%@page import="shoppingBasket.CommoditiesListRemote"%> 
<%@page import="java.util.List"%> 
<%@page import="java.util.Iterator"%> 
<%@page import="dataObjects.Commodity"%> 
<%@page import="java.text.NumberFormat"%>

<%@page import="java.util.Locale"%>


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html> <head>
<meta http-equiv="Content-Type" content="text/html;   charset=cp1251">
<title>Cigarette store</title>
</head>
<body>
<h1>Welcome to the finest internet cigarettes store!</h1>
<h2>Here is the list of commodities available for purchase</h2>
// Переход к корзине с товарами
<a href="basket.jsp">Goto Basket</a><br>
// Переход к предыдущим заказам
<a href="prevorders.jsp">View previous orders</a><br>
<table border="0" cellpadding="0" cellspacing="0">
<%
// Получаем удаленный интерфейс ComoditiesListBean
CommoditiesListRemote remote =   (CommoditiesListRemote) 
	session.getAttribute("commoditiesbean");
List list = remote.getAvailableCommodities();

NumberFormat format = NumberFormat.getCurrencyInstance(Locale.US);
for   (Iterator iter = list.iterator();  iter.hasNext();)   
{ Commodity commodity =   (Commodity)   iter.next();
%>
<tr>

<td style="padding-left:10px;  padding-right:10px;"> 
<%=commodity.getName()%>
</td>
<td style="padding-left:10px;  padding-right:10px;"> 
<%=commodity.getDescription()%> </td>
<td style="padding-left:10px;  padding-right:10px;"> 
<%=format.format(commodity.getPrice())%> </td>

// Ссылка на сервлет AddToServlet
<td style="padding-left:10px;  padding-right:10px;"> <a
href="addtocart?good id=<%=commodity.getId()%>">Add to cart</a> </td>

<td style="padding-left:10px;  padding-right:10px;">
<img src="<%=commodity.getImagePath()%>"/></td>
</tr>

<%
}
%>
</table>
// Переход к странице с корзиной для того,  чтобы оформить заказ
<a href="basket.jsp">Make order</a><br>
// Выход из системы посредством LogoutServlet
<a href="logout">Logout</a>
</body> </html>
Доступные товары

увеличить изображение
Рис. 3.42. Доступные товары

Страница с фотографиями товаров (сигарет) изображена на Рис. 3.42. Сервлет AddToCartServlet получает в качестве параметра ID товара, из контекста сессии берет удаленный интерфейс ShoppingListBean,а затем выполняет вызов addCommodity (goodId). Стоит отметить, что ни сервлет, не компонент не проверяют факта существования товара с таким ID. Поэтому пользователь может "обмануть" магазин передав заведомо неправильный good_id в сервлет.

public class AddToCartServlet extends HttpServlet  
{
private static final long serialVersionUID = -666156591413576322L;
public AddToCartServlet()  
	{
	super();
	}
protected void doPost(HttpServletRequest req,  HttpServletResponse res)   
	{ 
	doGet(req,   res);
	}

protected void doGet(HttpServletRequest req,  HttpServletResponse res)   
	{ 
	HttpSession session = req.getSession(); 
	ShoppingBasketRemote remote =   (ShoppingBasketRemote)
	session.getAttribute("basketbean"); 
	String strGoodId = req.getParameter("good id"); 
	int goodId = 0;
	
	try 
		{
		goodId = Integer.parseInt(strGoodId); 
		}   
	catch   (NumberFormatException e)   
		{ 
		goodId = 0;
		}
	
	if   (goodId > 0 && remote   != null)   
		{
		try 
		{
		remote.addCommodity(goodId); 
		}  
		catch   (RemoteException e)   
		{
		e.printStackTrace();
		}
		}

	RequestDispatcher reqDispatcher = getServletContext().getRequestDispatcher("/goodlist.jsp");
	try 
		{
		reqDispatcher.forward(req,   res); 
		}   
	catch   (java.io.IOException e)   
		{
		e.printStackTrace(); 
		}   
	catch   (javax.servlet.ServletException e)   
		{
		e.printStackTrace();
		}
	}
}
Антон Зубеков
Антон Зубеков

Здравствуйте, подскажите пожалуйста где можно достать материалы по курсу Кросс-платформенные и многозвенные технологии, о которых говориться, к примеру, в Лекции 2. Пример "Служба мгновенных сообщений"