Уровень сложности: средний Марк Тэлбот, разработчик отраслевых решений,
IBM
Кулвир Сингх Бхогал (Kulvir Singh Bhogal), программное обеспечение для WebSphere, Fort Worth, TX, IBM
13.04.2007 В данной статье мы покажем, как создать бот, извлекающий информацию о котировках для IBM Lotus Sametime Connect, используя набор инструментальных программ IBM Lotus Sametime Java. StockBot использует Web-сервис для извлечения информации о котировках акций с Web-сайта Yahoo! Finance.
В статье developerWorks Lotus "Создание программ-роботов Sametime, Часть 1" рассматривалось, как создавать боты IBM Lotus Sametime, используя пример Magic Eightball. После публикации этой статьи и с появлением IBM Lotus Sametime V7.5 набор программ Lotus Sametime претерпел значительные изменения. В данной статье рассматриваются эти изменения, и продолжается обсуждение ботов путем создания программы, предоставляющей информацию о котировках акций. Эта информация извлекается через Web-сервис, создаваемый с использованием IBM Rational Application Developer V6.0.
Хотя мы и повторяем некоторую информацию о ботах, но не детально. Вместо этого предлагаем вам познакомиться с темой ботов самостоятельно и прочитать статьи, ссылки на которые приведены в разделе "Ресурсы". Также, если вы не знакомы с Web-сервисами, можете просмотреть материал на странице developerWorks "SOA и Web Services для новичков".
Sametime-боты и набор программ IBM Lotus Sametime Java
Термин бот (bot) происходит от слова робот и используется для описания программы, принимающей указания от пользователя и предоставляющей ответ. Sametime-боты представляют собой вид ботов, которые подключаются к функциям оповещения о присутствии и системы мгновенного обмена сообщениями Lotus Sametime.
Sametime-бот отображается пользователям IBM Lotus Sametime Connect как активный субъект в списке контактов. На рисунке 1 показан предварительный вид программы Lotus Sametime Connect, взаимодействующей со StockBot, ботом, разрабатываемым в этой статье.
Рисунок 1. StockBot
Бот можно научить выполнять такие действия как предоставление информации по требованию пользователей. Но как научить? Это делается программно при помощи набора программ IBM Lotus Sametime Java.
Набор программ Lotus Sametime Java используется для локальной и серверной разработки. Он позволяет добавлять функции Lotus Sametime к Java-приложениям. Руководство по этому набору программ, поставляемое с IBM Lotus Sametime Software Development Kit (SDK), описывает Lotus Sametime Java Toolkit как "набор строительных блоков или компонентов, предназначенных для использования разработчиками при создании приложений, применяющих функциональность и сервисы Lotus Sametime".
Начиная с Lotus Sametime V7.5, все наборы клиентских и серверных программ Lotus Sametime объединяются в общий пакет Lotus Sametime SDK. Загрузить SDK можно со страницы developerworks Lotus Toolkits.
Использование IBM Rational Application Developer для разработки
Использовать компоненты набора программ Lotus Sametime можно в любой среде Java-разработки, поддерживающей Java Development Kit 1.4.2 или 1.5. Для разработки нашего бота мы используем IBM Rational Application Developer V6. Rational Application Developer - это мощная интегрированная среда разработки (integrated development environment - IDE), основанная на платформе Eclipse.
Поскольку данная статья не является учебником по Rational Application Developer, мы предполагаем, что вы знаете, как использовать эту среду разработки. Если это не так, рекомендуем вам просмотреть страницу developerWorks Rational Application Developer для WebSphere Software. Rational Application Developer поставляется со встроенной тестовой средой IBM WebSphere Application Server V6, которую можно использовать при разработке корпоративных приложений.
Использование IBM Lotus Sametime 7.5 Demonstration Site в качестве "песочницы"
Для создания бота необходимо зарезервировать Sametime ID для него. В нашем тестировании и разработке мы используем IBM Lotus Sametime 7.5 Demonstration Site, где необходимо создать два Sametime ID, один для бота и один для пользователя, способного обращаться к боту. Настройте Lotus Sametime Connect на подключение к серверу stdemo3.dfw.ibm.com, выбрав File - Preferences, затем Communities в левой навигационной панели диалогового окна Preferences, а затем нажав кнопку Add New Community.
В следующей закладке Log In, введите регистрационную информацию (имя пользователя и пароль Sametime Demonstration Site) для вашего пользователя Sametime. Выберите закладку Server (рисунок 2), введите stdemo3.dfw.ibm.com в поле Host server и 1533 в поле Community port, а затем нажмите кнопку OK.
Рисунок 2. Добавление сообщества Sametime для тестирования и разработки
Создание и освоение StockBot
Как упоминалось ранее, мы создаем бот, предоставляющий информацию о котировках акций; отсюда его имя - StockBot. Вопрос заключается в том, как получить данную информацию? Для этого надо подключиться к потоку информации, предоставляемому Web-сайтом Yahoo! Finance. В частности, мы используем функцию Yahoo, возвращающую котировки акций в CSV-формате (разделенные запятыми значения).
Вот пример значения в CSV-формате, возвращаемого для акций IBM:
"IBM",93.86,"N/A"
Точнее, мы интересуемся вторым значением (93.86 в нашем примере), являющимся стоимостью последней сделки (обычно называемой котировкой акции). Для получения такой котировки нужно подключиться к следующему URL:
http://finance.yahoo.com/d/quotes.csv?f=sl1e1&e=.csv&s=
объединенному с символом акции, которая ищется. Например, если ищется акция IBM, URL такой:
http://finance.yahoo.com/d/quotes.csv?f=sl1e1&e=.csv&s=IBM
Используйте f=sl1e1 в URL для указания того, чтобы Yahoo возвратил символ (представленный как s), стоимость последней сделки (l1), и индикацию ошибки (e1) при предоставлении вами сервиса с неправильным символом. Позже вы будете использовать также встроенные сетевые возможности Java, предоставляемые в пакете java.net, для подключения к Web-сайту Yahoo! Finance и получения информации о котировках акций.
Создание класса StockQuoter
Ниже приведен исходный код класса com.devworks.example.StockQuoter. Ссылку на этот и остальные исходные коды, используемые в данной статье, можно найти в разделе "Загрузка".
Листинг 1. Класс com.devworks.example.StockQuoter
public class StockQuoter {
private static String YAHOO_URL =
"http://finance.yahoo.com/d/quotes.csv?f=sl1e1&e=.csv&s=";
Pattern p = Pattern.compile("N/A");
private static final float
INVALID_SYMBOL_RETURN_VALUE = -999.999F;
public float getQuote(String symbol) throws Exception
{
String compositeURL = YAHOO_URL + symbol;
URL url = new URL(compositeURL);
InputStream is = url.openStream();
Reader reader =
new BufferedReader(new InputStreamReader(is));
StreamTokenizer st = new StreamTokenizer(reader);
// извлечь первый маркер - должен быть символом
st.nextToken();
String returnedSymbol = st.sval;
if (!returnedSymbol.equals(symbol))
throw
new Exception("A problem occurred with the stock service");
else
{
st.nextToken(); // пропустить запятую
st.nextToken(); // получить котировку
float quote = (float)st.nval;
st.nextToken(); // пропустить запятую
st.nextToken(); // получить ошибку
String sError = (String)st.sval;
Matcher myMatcher = p.matcher(sError);
boolean found = myMatcher.find();
if (found) return quote;
else return INVALID_SYMBOL_RETURN_VALUE;
}
|
Как видите, объект java.io.InputStream используется для открытия указанного URL finance.yahoo.com для запрашиваемого символа. Как рассматривалось ранее, URL представляет собой объединение finance.yahoo.com с символом, обозначающим желаемую котировку. Для синтаксического разбора информации, возвращенной после посещения этого URL, используется класс StreamTokenizer. Затем ищется маркер, соответствующий котировке, и возвращается в виде числа с плавающей запятой.
Если пользователь случайно передаст неверный символ акции в метод getQuote, сервис Yahoo возвратит строку, предупреждающую о возникновении ошибки. Если все хорошо, возвратится строка N/A. Обратите внимание на то, что для анализа присутствия строки N/A в полученной от Yahoo информации используется регулярное выражение. Если этой строки нет, потребителю метода возвращается фиктивное значение -999.99F, который интерпретирует его как вызов неправильного символа акции.
Кроме метода getQuote класс содержит метод main, который может быть использован для модульного тестирования метода getQuote.
Предыдущий исходный код должен размещаться в папке Java Source создаваемого в Rational Application Developer проекта Dynamic Web Project. Для нашего проекта Dynamic Web Project мы использовали имя StockQuoteWebProject. В свою очередь, StockQuoteWebProject должен размещаться в проекте Enterprise Application Project. Мы назвали наш проект Enterprise Project StockQuoteEARProject. Структура проекта отображается в Project Explorer программы Rational Application Developer так, как показано на рисунке 3.
Рисунок 3. Структура проекта в Project Explorer
Создание Web-сервиса StockQuote
На данном этапе наш Sametime-бот может взаимодействовать напрямую с классом StockQuoter. Однако для демонстрации удобств создания Web-сервиса в Rational Application Developer и простоты использования мастеров IDE для создания клиентского прокси мы хотим показать, как создать бот, использующий Web-сервис.
Для предоставления класса com.devworks.example.StockQuoter в виде Web-сервиса в Rational Application Developer выберите File - New - Other. В следующем диалоговом окне убедитесь в том, что отмечен флажок Show All Wizards, разверните каталог Web Services, выберите Web Service и нажмите кнопку Next (см. рисунок 4).
Рисунок 4. Выбор мастера Web Service
В следующей панели Web Service убедитесь, что отмечен тип Web-сервиса "Java bean Web Service" и снята отметка с флажка Generate a proxy (мы сгенерируем прокси позднее), а затем нажмите кнопку Next.
В панели Object Selection Page проверьте, что com.devworks.example.StockQuoter перечислен в поле Bean, затем нажмите кнопку Next. В панели Service Deployment Configuration проверьте, что Service project установлен в StockQuoteWebProject и что EAR project установлен в StockQuoteEARProject (см. рисунок 5).
Рисунок 5. Указание проектов, использующихся для Web-сервиса
Затем убедитесь в том, что панель Service Endpoint Interface Selection показывает com.devworks.example.StockQuoter как bean-компонент и com.devworks.example.StockQuoter_SEI как интерфейс оконечной точки сервиса. Параметр "Use an existing service endpoint interface" (Использовать существующий интерфейс оконечной точки сервиса) не должен быть отмечен. Нажмите кнопку Next.
В панели Web Service Java Bean Identity выберите только метод getQuote, поскольку мы не хотим отображать метод main через Web-сервис, а затем нажмите кнопку Next. Наконец, в панели Web Service Publication удостоверьтесь, что не отмечены оба параметра "Launch the Web Services Explorer to publish this Web service to the Unit Test UDDI Registry" (Запустить Web Services Explorer для публикации этого Web-сервиса в Unit Test UDDI Registry) и "Launch the Web Services Explorer to publish this Web service to a UDDI Registry" (Запустить Web Services Explorer для публикации этого Web-сервиса в UDDI Registry), поскольку мы не хотим публиковать сервис в UDDI-реестре.
Вскоре Rational Application Developer создаст Web-сервис. Можно использовать различные возможности Rational Application Developer для модульного тестирования работы Web-сервиса. Здесь мы не будем обсуждать данный процесс; если вы не знаете, как это сделать, обратитесь в раздел "Ресурсы", где приведены ссылки на дополнительную информацию.
Обратите внимание на то, что мастер Rational Application Developer создал несколько программных артефактов, включая WSDL-файл (Web Services Description Language (WSDL)) с именем StockQuoter.wsdl. Вы должны увидеть этот файл при выборе Dynamic Web Project и развертывании папок StockQuoteWebProject, WebContent, wsdl, com, devworks и example.
Создание прокси StockQuote Web Service Client
Теперь, когда уже есть Web-сервис, все готово для его использования. Rational Application Developer позволяет избежать запутанной реализации потребления Web-сервиса путем создания Java прокси-класса, выполняющего основную работу за вас. Этот прокси-класс размещается с клиентом, которым в нашем случае является бот. Для простоты предположим, что клиент и сервер расположены на одной и той же машине.
В Rational Application Developer выберите File - New - Other (сначала убедившись, что выбран вариант Show All Wizards в окне Select a wizard). Разверните Web Services, выберите Web Service Client и нажмите кнопку Next. В следующей панели Web Services выберите в поле Client proxy type вариант Java proxy и нажмите кнопку Next.
Затем нужно указать Rational Application Developer месторасположение WSDL-файла, который был создан при создании Web-сервиса. Нажмите кнопку Browse, в появившемся окне Resource browser разверните папки StockQuoteWebProject, WebContent, wsdl, com, devworks, example и выберите StockQuoter.wsdl (см. рисунок 6). Затем нажмите кнопку OK.
Рисунок 6. Выбор файла StockQuoter.wsdl
В панели Client Environment Configuration выберите в поле Client type значение Java и укажите в поле Client project name имя StockBotProject. Как будет видно позже, мы также используем этот проект для размещения нашего бота. В последней панели мастера Web Service Client нажмите кнопку Finish для завершения создания Java-прокси (см. рисунок 7).
Рисунок 7. Завершение мастера Web Service Client
На данном этапе, если вы переключитесь в Java-перспективу, то увидите новый проект под названием StockBotProject, в котором есть несколько классов, сгенерированных программой Rational Application Developer автоматически (см. рисунок 8). Proxy-класс имеет название StockQuoterProxy.java.
Рисунок 8. Proxy-класс, автоматически сгенерированный программой Rational Application Developer
Анализируя класс StockQuoterProxy, вы должны увидеть метод getQuote. Позже мы покажем, как StockBot использует этот метод для реализации функционирования вашего Web-сервиса котировок акции.
Создание StockBot
Для разработки StockBot будем использовать набор программ Lotus Sametime Java. Набор программ Lotus Sametime V7.5 Java toolkit можно использовать для реализации, например, Sametime-чата на Web-сайте вашей компании для организации мгновенной связи посетителей сайта с отделом продаж, настройки Lotus Sametime под ваши бизнес-требования, или для создания собственных Sametime-приложений на Java.
Во-первых, нужно выполнить некоторую дополнительную работу для подготовки Java-проекта к созданию Sametime-бота. В частности, необходимо добавить файлы STComm.jar, stcommsrvrtk.jar и stjavatk.jar из набора программ Lotus Sametime Java toolkit в Java Build Path вашего проекта StockBotProject. Для этого выполните следующие действия:
- В Rational Application Developer нажмите правой кнопкой мыши на StockBotProject в виде Package Explorer и выберите пункт Properties.
- В диалоговом окне Properties выберите Java Build Path в левой навигационной панели для изменения свойств Java Build Path.
- Выберите закладку Libraries (см. рисунок 9).
- Нажмите кнопку Add External JARs для добавления JAR-файлов Sametime Java Client. Три указанных выше JAR-файла включены в Lotus Sametime Java Toolkit.
Рисунок 9. Изменение Java Build Path для включения необходимых JAR-файлов
Класс StockService
Sametime-бот состоит из двух созданных вами классов, а именно StockService и StockQuoteBot. Основная часть логики бота находится в классе StockService, реализующем следующие Sametime-интерфейсы :
Листинг 2. Sametime-интерфейсы
com.lotus.sametime.community.LoginListener
com.lotus.sametime.community.ServiceListener
com.lotus.sametime.im.ImServiceListener
com.lotus.sametime.community.ImListener
|
Создайте класс StockService в пакете com.devworks.example.bot в проекте StockBotProject Java. Можно импортировать код этого класса из загружаемого файла, поставляемого с данной статьей.
Теперь проанализируем содержимое класса StockService. Конструктор создает новый объект STSession, используя строку, представляющую уникальное имя сессии для Java Virtual Machine, в которой выполняется бот. Объект STSession содержит набор компонентов, связанных с Sametime-сессией. После создания объекта STSession загрузите используемые ботом компоненты и запустите Sametime-сессию.
Листинг 3. Класс StockService
private STSession session;
public StockService(String sessionName) throws DuplicateObjectException {
session= new STSession(sessionName);
session.loadSemanticComponents();
session.start();
}
|
После создания Sametime-сессии можно подключиться к Sametime-сообществу. Класс CommunityService позволяет классу StockService зарегистрироваться на сервере Lotus Sametime. Для того чтобы бот получал ответы на свои запросы (например, запрос на регистрацию), он должен иметь соответствующие прослушиватели (listeners), связанные с ним. Первым прослушивателем, связываемым с классом StockService, является com.lotus.sametime.community.ServiceListener. ServiceListener обеспечивает обновления, связанные с доступностью серверных компонентов, в ответ на запрос объекта CommunityService. После добавления ServiceListener вызывается private-метод login, как показано в листинге 4.
Листинг 4. Класс CommunityService
private CommunityService service;
public void start(String server, String username, String password)
{
service = (CommunityService)session.getCompApi(CommunityService.COMP_NAME);
service.addServiceListener(this);
login(server, username, password);
}
|
В следующем методе login вы связываете com.lotus.sametime.community.LoginListener с объектом CommunityService. Поскольку класс StockService также реализует интерфейс LoginListener, можно использовать его в качестве аргумента. После связывания LoginListener можно зарегистрироваться на сервере Lotus Sametime, используя имя сервера, имя пользователя и пароль:
Листинг 5. Метод login
private void login(String server, String username, String password)
{
service.addLoginListener(this);
service.loginByPassword(server,username,password);
}
|
Интерфейс com.lotus.sametime.community.LoginListener имеет два метода обратного вызова, которые должны быть реализованы. Метод loggedIn вызывается при успешной регистрации, а метод loggedOut вызывается при выходе из системы. Метод loggedOut активизируется после безуспешных регистраций, а также после успешных выходов из системы. При реализации вашего собственного метода loggedOut проверьте причину выхода из системы и отобразите ее на системной консоли:
Листинг 6. Метод loggedOut
public void loggedOut(LoginEvent event)
{
int reason = event.getReason();
if (reason == 0)
System.out.println("Successfully logged out.");
else
System.out.println("Failed to login. Return Code =" + reason);
session.stop();
session.unloadSession();
}
|
В следующем методе loggedIn настраивается объект InstantMessagingService. Объект InstantMessagingService похож на объект CommunityService в том, что он имеет набор методов и прослушивателей. Интерфейс IMServiceListener позволяет прослушивать сообщения, получаемые ботом от пользователей:
Листинг 7. Метод loggedIn
InstantMessagingService imService;
public void loggedIn(LoginEvent event)
{
imService = (InstantMessagingService)
_session.getCompApi(InstantMessagingService.COMP_NAME);
imService.registerImType(ImTypes.IM_TYPE_CHAT);
imService.addImServiceListener(this);
System.out.println("Logged In");
}
|
Интерфейс IMServiceListener имеет один метод обратного вызова, imReceived, который вызывается каждый раз, когда пользователь открывает новое окно системы мгновенного обмена сообщениями для подключения к боту. Для прослушивания сообщений и данных, передаваемых пользователем из этого окна, должна быть создана реализация ImListener. Также, поскольку наш бот является дружелюбным, он посылает приветствие каждый раз, когда пользователь подключается к нему:
Листинг 8. Метод imReceived
String welcomeMessage = "Welcome to the StockBot.
Enter a stock symbol.";
public void imReceived(ImEvent arg0) {
System.out.println("im received");
arg0.getIm().sendText(false, welcomeMessage);
arg0.getIm().addImListener(this);
}
|
К методам обратного вызова StockImListener относятся dataReceived, textReceived, imClosed, openImFailed и imOpened. Наш бот отвечает только методам textReceived и imClosed. Когда пользователь закрывает свое окно системы мгновенного обмена сообщениями, прослушиватель удаляется, предохраняя бот от использования системных ресурсов для тех пользователей, которые больше не используют его:
Листинг 9. Метод imClosed
public void imClosed(ImEvent arg0) {
System.out.println("Im Closed");
arg0.getIm().removeImListener(this);
}
|
Ответ StockBot на обратный вызов textReceived является тем, из-за чего StockBot получил свое имя. В нашей реализации textReceived мы получаем запрошенный символ акции. Затем вызывается getQuoteString (удобный метод связи с Web-сервисом котировок акций) для активизации созданного вами ранее Web-сервиса. Если пользователь введет help, бот передаст сообщение, содержащее инструкции по взаимодействию с ботом:
Листинг 10. Метод textReceived
String helpMessage = "Enter a stock symbol and I will return a price.";
public void textReceived(ImEvent arg0) {
String stockSymbol = arg0.getText();
String stringPriceMessage;
if (stockSymbol.equals("help"))
stringPriceMessage = helpMessage;
else
stringPriceMessage = getQuoteString(stockSymbol);
arg0.getIm().sendText(true, stringPriceMessage);
}
|
Следующий метод getQuoteString содержит логику для поиска символа акции, используя класс StockQuoterProxy, сгенерированный вами ранее. Метод getQuoteString возвращает либо стоимость акции, либо сообщение, указывающее на проблему в запросе пользователя:
Листинг 11. Метод getQuoteString
private String getQuoteString(String stockSymbol) {
String stringPriceMessage;
try {
float stockPrice = 0.0f;
StockQuoterProxy proxy = new StockQuoterProxy();
proxy.getQuote(stockSymbol);
stockPrice = stockLookup.getQuote(stockSymbol.trim());
if (stockPrice != -999.99f)
stringPriceMessage =
String.valueOf(stockPrice);
else
stringPriceMessage =
"I'm sorry I had trouble with your request.";
} catch (RemoteException e) {
stringPriceMessage =
"I'm sorry I had trouble with your request.";
} catch (Exception e) {
stringPriceMessage =
"I'm sorry I had trouble with your request.";
}
return stringPriceMessage;
}
|
Управление ботом с использованием класса StockQuoteBot
Класс StockQuoteBot обеспечивает функциональность командной строки для бота. Класс извлекает информацию о сервере Lotus Sametime, к которому должен подключиться, а также полномочия пользователя в виде аргументов командной строки. Класс регистрируется в системе, используя экземпляр класса StockService, описанного ранее. При нажатии клавиши на клавиатуре StockBot завершается:
Листинг 12. Класс StockQuoteBot
public class StockQuoteBot {
public static void main(String[] args) {
StockService service = new StockService();
String server = args[0];
String userID = args[1];
String password = args[2];
service.start(server, userID, password);
System.out.println("Stock Quote Bot is Running. Press any key to terminate.");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
br.readLine();
} catch (IOException e) {
System.out.println("error");
}
service.stop();
System.out.println("Stock Quote Bot has terminated");
}
}
|
Использование StockBot
Теперь, когда вы завершили разработку бота, можно легко запустить его в тестовой среде Rational Application Developer. Для этого нажмите правой кнопкой мыши на файле StockQuoteBot.java и выберите Run - Run.
На данном этапе отображается диалоговое окно Run, как показано на рисунке 10, то есть, имеется возможность передать аргументы командной строки в StockBot. В панели Configurations выберите Java Application и нажмите кнопку New. Появится конфигурация Java Application для класса StockQuoteBot. После этого перейдите на закладку Arguments. Для нашей программы вводимыми аргументами являются 192.168.19.128 "Stock Quote Bot" ibm, которые указывают адрес нашего сервера Lotus Sametime, ID пользователя и пароль соответственно.
Рисунок 10. Настройка StockBot на работу внутри Rational Application Developer
После запуска класса бота в консоли отображается подтверждение об успешной регистрации в системе Sametime-бота (см. рисунок 11).
Рисунок 11. Консоль Rational Application Developer отображает выходную информацию бота StockBot
Теперь, когда бот выполняется, можно зарегистрироваться на вашем сервере Lotus Sametime с использованием Lotus Sametime Connect и поработать с StockBot, как показано на рисунке 12. Для этого необходимо добавить ID Sametime-партнера, полученного для StockBot.
Рисунок 12. Взаимодействие с StockBot
Заключение
В данной статье мы продемонстрировали, как создать Sametime-бот, который покорно слушает вопросы и отвечает на них. В частности, был создан Web-сервис котировок акций, который обращается к Web-сайту Yahoo! Finance для получения информации о котировках. Затем был создан бот для доступа к Web-сервису; в свою очередь, клиенты могут общаться с ботом и получать котировки акций по запросу.
В родственной статье developerWorks Lotus "Создание Lotus Sametime-бота для перевода с одного языка на другой" мы рассказываем, как создать Sametime-бот, работающий совместно с IBM WebSphere Translation Server для предоставления сервиса перевода с языка на язык. Виды ботов, которые можно создать, ограничены только вашим воображением. Мы надеемся, что эта статья поможет вам чувствовать себя более комфортно с API, которые нужно использовать для создания ботов. Успешного строительства ботов
Загрузка | Описание | Имя | Размер | Метод загрузки |
|---|
| Пример кода StockBot | stockquoteBotExample.zip | 10 KB | HTTP |
|---|
Ресурсы Научиться
Получить продукты и технологии
Обсудить
Об авторах  | |  | Марк Тэлбот (Mark Talbot) - разработчик отраслевых решений в компании IBM. Вы можете связаться с Марком по адресу talbotm@us.ibm.com. |
 | |  | Кулвир Сингх Бхогал работает в качестве консультанта IBM; он разрабатывает и реализует решения на основе Java для сайтов клиентов по всей стране. |
Выскажите мнение об этой странице
|