/bin/https/bin в PATH на Windows NT-платформах.
Вам нужно компилировать только те страницы, которые содержат серверный JavaScript или оба - клиентский и серверный JavaScript. Вам не нужно компилировать страницы, содержащие только клиентский JavaScript. Вы, конечно, можете сделать это, но скорость работы будет выше, если Вы оставите страницы с клиентским JavaScript без компиляции.
Компилятор доступен из командной строки. Используйте следующий синтаксис командной строки для компиляции и компоновки приложений JavaScript на сервере:
jsac [-h] [-c] [-v] [-d] [-l] [-o outfile.web] [-i inputFile] [-p pathName] [-f includeFile] [-r errorFile] [-a 1.2] script1.html [...scriptN.html] [funct1.js ... functN.js]
Элементы в квадратных скобках не обязательны. Синтаксис дан на нескольких строках для большей ясности. Файлы scriptN.html и functN.js это входные файлы для компилятора. Должен быть как минимум один HTML-файл. По умолчанию файлы HTML и JavaScript ищутся в текущей директории. Специфицируемые Вами файлы обязаны быть JavaScript- или HTML-файлы; Вы не можете специфицировать другие файлы, такие, например, как .GIF.
На всех платформах Вы можете использовать тире (-) или слэш (/) для обозначения опций командной строки. То есть, следующие строки эквивалентны:
jsac -h jsac /h
Заметьте, что, поскольку слэш обозначает опции командной строки, входной файл не может начинаться с символа / (слэш) для обозначения абсолютного пути (в Unix). Таким образом, следующий вызов неверен:
jsac -o myapp.web /usr/vpg/myapp.html
Это ограничение не распространяется на путь, который Вы предоставляете как аргумент командной строки; только на входные файлы. В NT Вы можете использовать обратный слэш (\) для указания абсолютного пути во входном файле, как в следующем вызове:
jsac -o myapp.web \usr\vpg\myapp.html
В Unix Вы обязаны использовать опцию командной строки -i для специфицирования абсолютного пути, как описано ниже.
Доступны следующие опции командной строки:
-h: Помощь по синтаксису компилятора. Если Вы используете эту опцию, не указывайте никаких других.
-c: Синтаксис только проверяется; web-файл не генерируется. Если эта опция указана, опцию -o указывать не нужно.
-v: (Verbose) Выводит информацию о работе компилятора.
-d: Выводит генерируемое JavaScript-содержимое.
-l: Специфицирует набор символов, используемый при компиляции (такой как iso-8859-1, x-sjis или euc-kr) .
-o outfile: Создаёт web-файл в формате байт-кода с именем outfile.web. Если эта опция не указана, компилятор не генерирует web-файл. (Опускайте эту опцию только тогда, когда используете опцию -c для проверки синтаксиса или -h для получения помощи.)
-i inputFile: Позволяет специфицировать входной файл с полным путём, а не с относительным путём. Для этой опции может быть задано только имя файла. Если Вам нужно специфицировать несколько файлов с полным путём, используйте опцию -f.
-p pathName: Специфицирует корневую директорию для всех относительных путей, используемых при компиляции. (Используйте перед опцией -f.) Для этой опции можно указать только один путь.
-f includeFile: Специфицирует файл, который является списком входных файлов, что позволяет обойти ограничение на количество символов, вводимых в командной строке. Для этой опции можно указать только одно имя файла. Файлы в списке входных файлов в includeFile разделены пробелами. Если имя файла содержит пробел, Вы обязаны заключить имя файла в двойные кавычки.
-r errorFile: Перенаправляет стандартный вывод (включая сообщения об ошибках) в специфицированный файл. В этой опции можно указать только одно имя файла.
-a 1.2: Устанавливает версию в 1.2 для обеспечения обратной совместимости.
Например, следующая команда компилирует и компонует две HTML -страницы с JavaScript, main.html и hello.html, и файл серверного JavaScript, support.js, создавая двоичный исполняемый файл с именем myapp.web. Кроме того, в процессе компиляции компилятор печатает в командной строке информацию о ходе компиляции.
jsac -v -o myapp.web main.html hello.html support.js
В следующем примере команда компилирует файлы, перечисленные в файле looksee.txt, в бинарный исполняемый файл под названием looksee.web:
jsac -f looksee.txt -o looksee.web
Здесь looksee.txt может содержать:
looksee1.html looksee2.html \myapps\jsplace\common.js looksee3.html
Конфигурирование Среды
Прежде чем Вы сможете запустить эти приложения, необходимо сделать незначительные изменения в исходных файлах и создать базу данных для видео. В данном разделе указывается, какие файлы Вы обязаны изменить и какие процедуры выполнить, чтобы внести эти изменения и создать БД для каждого из поддерживаемых серверов БД. См. конкретную информацию в разделе, посвящённом Вашему серверу БД.
ПРИМЕЧАНИЕ:
Ваш сервер БД обязан быть настроен и запущен перед началом создания видео-БД, и Вы обязаны сконфигурировать сервер и клиента БД так, как указано в Кроме того, скрипты создания БД используют утилиты БД, поставляемые с Вашими БД. Вы уже должны знать, как пользоваться этими утилитами.
Конфигурирование Установок по Умолчанию
Чтобы конфигурировать установки по умолчанию для Application Manager, щёлкните Configure (в Enteprise Server 3.x) или Preferences (в Enterprise Server 4.0) в верхнем фрэйме Application Manager'а. В ответ Application Manager отобразит форму, показанную на .
Вы можете специфицировать следующие значения по умолчанию:
Web File Path: Путь по умолчанию к рабочей директории.
Default Page: Имя по умолчанию для страницы по умолчанию в новом приложении.
Initial Page: Имя по умолчанию для начальной страницы в новом приложении.
Built-in Maximum Database Connections: Значение по умолчанию - максимальное количество соединений с базами данных, которые могут устанавливаться для предопределённого объекта database.
External Libraries: Путь по умолчанию к директории с внешними исполняемыми библиотеками.
Client Object Maintenance: Техника по умолчанию для обслуживания свойств объекта client.
Если Вы устанавливаете новое приложение, используются значения полей по умолчанию в качестве начальных значений.
Дополнительно Вы можете специфицировать следующие установки:
Confirm on: Требовать ли Вашего подтверждения для выполнения удаления, старта, остановки или рестарта приложения.
Debug Output: Появляется ли окно трассировки, при отладке приложения, в том же окне, что и само приложение, но в отдельном кадре, или в отдельном от приложения окне.
Рисунок 3.6 Форма "Установки по Умолчанию"
Конструирование HTML-Страницы
Когда Вы компилируете приложение JavaScript, исходники состоят из HTML-страниц, содержащих операторы серверного JavaScript, и, возможно, HTML-страницы, не содержащие операторов серверного JavaScript. Если пользователь получает доступ к странице, которая не содержит серверных операторов, сервер высылает страницу обратно, как и любую другую HTML-страницу. Если пользователь получает доступ к странице, которая содержит серверные операторы, машина выполнения на сервере конструирует HTML-страницу для отправки в ответе, используя одну из исходных страниц Вашего приложения.
Машина выполнения сканирует исходную страницу. При обнаружении операторов HTML клиентского JavaScript она присоединяет их к создаваемой странице. При обнаружении операторов серверного JavaScript она выполняет их. Хотя большинство операторов серверного JavaScript выполняются на сервере, некоторые влияют на конструируемую страницу. В следующих разделах рассматриваются три функции: write, flush и redirect, которые влияют на обрабатываемую HTML-страницу.
Конвертация Данных
Есть два основных формата файлов : ASCII-текст и бинарный. Методы byteToString и stringToByte класса File конвертируют данные этих форматов.
Метод byteToString конвертирует число в односимвольную строку. Это static-метод. Вы можете использовать класс File сам по себе, а не его экземпляр, для вызова этого метода.
File.byteToString(number);
Если аргумент - не число, метод возвращает пустую строку.
Метод stringToByte конвертирует первый символ своего аргумента, строку, в число. Это также static-метод.
File.stringToByte(string);
Метод возвращает числовое значение первого символа или 0.
Конвертация из Java в JavaScript
Значения, переданные из Java в JavaScript конвертируются так:
Java byte, char, short, int, long, float и double конвертируются в числа JavaScript.Java boolean конвертируется в JavaScript boolean. Объект класса netscape.javascript.JSObject конвертируется в оригинальный JavaScript-объект.
Java-массивы конвертируются в объект JavaScript pseudo-Array; этот объект ведёт себя так же, как объект JavaScript Array: Вы можете иметь к нему доступ с синтаксисом arrayName[index] (где index это целое число) и определять его размер с помощью arrayName.length.
Java-объект любого иного класса конвертируется в JavaScript-оболочку, которая может использоваться для доступа к методам и полям Java-объекта:
Конвертация оболочки в строку вызывает метод toString объекта-оригинала.Конвертация в число вызывает метод doubleValue, если возможно, иначе - терпит неудачу.
Конвертация в boolean вызывает метод booleanValue, если возможно, иначе - терпит неудачу.
Обратите внимание, что экземпляры java.lang.Double и java.lang.Integer конвертируются в объекты JavaScript, а не в числа JavaScript. Аналогично, экземпляры java.lang.String также конвертируются в JavaScript-объекты, а не в строки JavaScript.
Java String -объекты также соответствуют оболочкам JavaScript. Если Вы вызываете JavaScript-метод, который требует строки JavaScript, и передаёте его данной оболочке, Вы получите ошибку. Вместо этого конвертируйте оболочку в строку JavaScript, присоединяя к ней пустую строку, как показано здесь:
var JavaString = JavaObj.methodThatReturnsAString(); var JavaScriptString = JavaString + "";
1
2
Конвертация из JavaScript в Java
Если Вы вызываете Java-метод и передаёте ему параметры из JavaScript, типы данных передаваемых параметров конвертируются в соответствии с правилами, описанными в следующих разделах:
Return-значения методов netscape.javascript.JSObject всегда конвертируются в экземпляры java.lang.Object. Правила конвертации этих return-значений также описаны в этих разделах.
Например, если JSObject.eval возвращает число JavaScript, Вы можете найти правило конвертации этого числа в экземпляр java.lang.Object в разделе .
Конвертация Типов Данных Базой Данных
В следующей таблице показана конвертация, выполняемая машиной выполнения JavaScript для баз данных DB2.
Тип Данных DB2
Тип Данных JavaScript char(n), varchar(n), long varchar, clob(n)
string integer, smallint integer
decimal, double double date, time, timestamp
Date blob Blob
В следующей таблице дана конвертация БД Informix.
Тип Данных Informix
Тип Данных JavaScript char, nchar, text, varchar, nvarchar string decimal(p,s), double precision, float, integer, money(p,s), serial, smallfloat, smallint number date, datetime Date byte Blob interval Не поддерживается
1
Тип даты Informix datetime имеет точность переменных, определяемых пользователем. Серверный JavaScript выводит данные datetime в формате от YEAR до SECOND. Если datetime -переменная была определена с другой точностью, такой как от MONTH до DAY, она может быть отображена некорректно. В данном случае дата не нарушится некорректным отображением.
ODBC транслирует типы данных продавца в типы данных ODBC. Например, в Microsoft SQL Server тип данных varchar конвертируется в ODBC-тип SQL_VARCHAR. Дополнительно см. документацию ODBC SDK.
В следующей таблице показана конвертация, выполняемая машиной JavaScript для баз данных ODBC.
Тип Данных ODBC
Тип Данных JavaScript
SQL_LONGVARCHAR, SQL_VARCHAR, SQL_CHAR
string SQL_SMALLINT, SQL_INTEGER, SQL_DOUBLE, SQL_FLOAT, SQL_REAL, SQL_BIGINT, SQL_NUMERIC, SQL_DECIMAL
number SQL_DATE, SQL_TIME, SQL_TIMESTAMP
Date SQL_BINARY, SQL_VARBINARY, SQL_LONGBINARY
Blob
В следующей таблице показана конвертация, выполняемая машиной выполнения JavaScript для баз данных Oracle.
Тип Данных OracleТип Данных JavaScript
long, char(n), varchar2(n), rowidstring
number(p,s), number(p,0), float(p) number date Date raw(n), long raw Blob
В следующей таблице показана конвертация, выполняемая машиной выполнения JavaScript для баз данных Sybase.
Тип Данных SybaseТип Данных JavaScript
char(n), varchar(n), nchar(n), nvarchar(n), text
string
bit, tinyint, smallint, int, float(p), double precision, real, decimal(p,s), numeric(p,s), money, smallmoney
number
datetime, smalldatetime
Date
binary(n), varbinary(n), image
Blob
1
Sybase- клиент ограничивает числовые типы данных 33 цифрами. Если Вы вставляете число JavaScript с большим количеством цифр в БД Sybase, Вы можете получить ошибку.
Конвертация Типов Данных
Поскольку Java является строго типизированным, а JavaScript - слабо типизированным языком, машина выполнения JavaScript конвертирует значения аргументов в подходящие типы данных других языков, если Вы пользуетесь LiveConnect. Эта конвертация описана в следующих разделах:
LiveConnect
Даёт возможность кодам на Java и JavaScript взаимодействовать друг с другом. Из JavaScript Вы можете инстанциировать Java-объекты и получать доступ к их public-методам и полям. Из Java Вы можете иметь доступ к объектам, свойствам и методам JavaScript.
Локализация Компилятора
Инсталяция Netscape-сервера не изменяет Вашу переменную окружения PATH для включения директории, в которой установлен компилятор приложений JavaScript. Если Вам необходим быстрый доступ к компилятору, Вы обязаны модифицировать эту переменную.
В системах Unix у Вас есть выбор способов изменения переменной окружения PATH. Можно добавить $NSHOME/bin/https/lib, где $NSHOME это директория, в которой установлен Ваш сервер. Поговорите с Вашим системным администратором о том, как это сделать.
Чтобы изменить системный путь NT, запустите Control Panel, найдите диалоговое окно System и установите переменную PATH в разделе Environment settings, включив в неё %NSHOME%\bin\https\bin, где NSHOME это директория, в которой установлен Ваш сервер.
Если вы переместили компилятор JavaScript-приложений в другое место, Вы обязаны добавить эту новую директорию в переменную PATH.
Локальный Informix
Если вы устанавливаете Informix локально, Вы обязаны установить клиента Informix до установки Informix-сервера.
Только для Unix: Если Вы используете 7.22 Online Server для Unix, процесс инсталяции создаёт соответствующую структуру директорий и файл sqlhosts. Вы обязаны установить переменные окружения, как для удалённого сервера.
Только для NT: Вы должны установить Online Server 7.20. Это установит также и клиента; дополнительные шаги не нужны. Если Ваш web-сервер запускается как System, убедитесь, что у вас запущен regcopy.exe.
Локальный Oracle
Только для Unix: Прежде чем Вы сможете подключиться к Oracle под Irix, Вы обязаны иметь соответствующие патчи для Irix. См. в информацию о необходимых патчах.
Все платформы: Вы обязаны установить Oracle Workgroup Enterprise Server 7.3.2 (NT) или Enterprise Server 7.3.x (Unix). Клиенты Oracle 7.1 и 7.2 не поддерживаются. Уточните у вашего поставщика сервера, совместима ли Ваша версия Oracle-сервера с Oracle-клиентом. Вы обязаны установить следующие переменные окружения:
ORACLE_HOME
Специфицирует директорию верхнего уровня, в которой установлен Oracle.
ORACLE_SID
Специфицирует Oracle System Identifier (Системный Идентификатор).
Если у Вас локальный сервер БД Oracle, Вы обязаны передавать пустую строку в качестве второго аргумента методу connect объектов database или DbPool или конструктору DbPool. Таким образом, эти методы используют значение переменной окружения ORACLE_SID. Например:
database.connect ("ORACLE", "" "user", "password", "");
Об инсталяции Oracle см. дополнительно документацию по Oracle.
Локальный Sybase
Только для Unix: Установите следующие переменные окружения:
SYBASE
Директория верхнего уровня, в которой установлен Sybase.LD_LIBRARY_PATH
(DEC) Обязана содержать $SYBASE/lib.
Для Solaris Вы обязаны также следовать инструкциям раздела
Все платформы: Установите Sybase SQL Server версии 11.1; клиентская часть устанавливается вместе с сервером. Поддерживаемые версии перечислены в разделе
Вы можете использовать подходящую утилиту Sybase для ввода в файл sql.ini (NT) и файл interfaces (все платформы) информации об удалённом сервере, с которым Вы хотите установить соединение. Дополнительно см. документацию Sybase.
Манипуляции с Результатами Выполнения Запросов с Помощью Ку́рсоров
Часто Вам необходимо не просто отобразить таблицу с результатами выполнения запроса, но изменить форматирование этих результатов или даже выполнить какую-нибудь их обработку. Для манипуляций результатами выполнения запроса Вы работаете с курсором БД, возвращаемым запросом к БД. Для создания экземпляра класса Cursor вызовите метод cursor объекта database или объекта Connection, передав ему оператор SQL SELECT в качестве параметра.
Вы можете представить курсор как виртуальную таблицу с рядами и столбцами, специфицированный по запросу. Курсор предполагает также понятие текущего ряда, который в реальности является указателем на ряд виртуальной таблицы. Когда Вы выполняете операции с курсором, они обычно воздействуют на текущий ряд.
По окончании работы, закройте курсор БД путём вызова его метода close. Соединение с БД не может быть освобождено, пока не закрыты все ассоциированные с ним курсоры. Например, если Вы вызываете метод release объекта Connection и это соединение имеет ассоциированный курсор, который не был закрыт, соединение не будет освобождено, пока курсор не будет закрыт.
В таблице обобщены методы и свойства класса Cursor.
Метод или Свойство
Описание
colName
Свойства, соответствующие каждому столбцу курсора. Имя каждого свойства colName это имя столбца в БД.
close
Закрывает курсор.
columns
Возвращает количество столбцов в курсоре.
columnName
Возвращает имя столбца в курсоре.
next
Делает следующий ряд курсора текущим рядом.
insertRow
Вставляет новый ряд в специфицированную таблицу.
updateRow
Обновляет записи в текущем ряду специфицированной таблицы.
deleteRow
Удаляет текущий ряд специфицированной таблицы.
Полную информацию об этих методах см. в описании класса Cursor в книге "Серверный JavaScript. Справочник".
Манипуляции с Запросами и Ответами
Обычный запрос, высылаемый клиентом на сервер, не имеет content type (тип содержимого). Машина выполнения JavaScript автоматически обрабатывает такие запросы. Однако, если пользователь отправляет форму, то клиент автоматически помещает content type в шапку/header, чтобы сообщить серверу, как интерпретировать данные формы. Этот content type обычно application/x-www-form-urlencoded. Машина выполнения также автоматически обрабатывает запросы с этим content type. В таких ситуациях Вам редко нужен прямой доступ к шапкам/header запроса или ответа. Если, однако, Ваше приложение использует иной content type, оно обязано уметь работать с шапкой запроса.
В свою очередь, типичный ответ сервера клиентку имеет тип содержимого text/html. Машина выполнения автоматически добавляет этот content type в свой ответ. Если Вам в ответе нужен другой content type, Вы обязаны предоставить его сами.
Для поддержки этих потребностей машина выполнения JavaScript на сервере даёт возможность Вашему приложению иметь доступ к (1) шапке/header любого запроса и к (2) телу запроса, имеющего нестандартный content type. Вы уже контролируете тело ответа тэгом SERVER и тэгами HTML. Функциональность, описанная в этом разделе, даёт также возможность управлять шапкой/header ответа.
Вы можете использовать эту функциональность в различных целях. Например, как описано в разделе , можно осуществлять связь серверных и клиентских процессов с помощью кук. Также Вы можете использовать эту функциональность для поддержки выгрузки файлов.
World Wide Web Consortium публикует онлайновую информацию о протоколе HTTP и о том, что может пересылаться по этому протоколу. См., например, .
Менеджер Приложений. Детали.
В этом разделе показано, как изменять установки по умолчанию для Application Manager. Кроме того, говорится о формате файла, в котором Application Manager хранит информацию.
Менеджер Приложений JavaScript. Обзор.
Прежде учиться создавать приложения JavaScript, Вы должны ознакомиться с Менеджером Приложений JavaScript. Вы можете использовать Application Manager для выполнения следующих задач:
Добавления нового JavaScript-приложения.
Модификации любых атрибутов уже установленного приложения.
Останова, старта и рестарта установленного приложения.
Запуска и отладки активного приложения.
Удаления установленного приложения.
Application Manager сам является приложением на JavaScript, демонстрирующим мощь и гибкость JavaScript. Вы запускаете JavaScript Application Manager по следующему URL в Navigator'е:
http://server.domain/appmgr
В ответ Application Manager отобразит страницу, показанную на для Netscape Enterprise Server 3.x и на Рисунке 3.3 - для Enterprise Server 4.0.
Рисунок 3.2 Application Manager в Enterprise Server 3.x
Рисунок 3.3 Application Manager в Enterprise Server 4.0
Application Manager отображает в прокручиваемом левом фрэйме (кадре/окне) все приложения JavaScript, установленные в данный момент на сервере. Выберите нужное приложение, щёлкнув на его имени в прокручиваемом списке.
Правый фрэйм отображает для выбранного приложения следующую информацию:
название приложения в верхней части фрэйма
путь к web-файлу приложения на сервере
начальную страницу и страницу по умолчанию
максимальное количество соединений с БД, допустимых для предопределённого объекта database
внешние библиотеки (если имеются)
технику обслуживания объекта client
статус приложения: active или stopped (Пользователи могут запускать только активные приложения. Остановленные приложения недоступны.)
Описание этих полей см. в разделе .
Для добавления нового приложения щёлкните вверху кнопку Add Application.
Щёлкните Configure (в Enteprise Server 3.x) или Preferences (в Enterprise Server 4.0) для конфигурирования установок по умолчанию для Application Manager.
Щёлкните Documentation, чтобы перейти на страницу технической поддержки Netscape JavaScript, где имеются ссылки на разнообразную документацию. Щёлкните Help для получения дополнительных инструкций об использовании Application Manager.
Методы и Свойства Результирующего Набора
В таблице дано резюме по методам и свойствам класса Resultset.
Метод или Свойство
Описание
colName
Свойства, соответствующие каждому столбцу результирующего набора. Имя каждого свойства это имя столбца в БД.
Поскольку хранимые процедуры Informix и DB2 не возвращают именованных столбцов, эти свойства не создаются для хранимых процедур Informix или DB2.
columns
Возвращает количество столбцов результирующего набора.
Для Informix этот метод возвращает количество return-значений для одного ряда.
columnName
Возвращает имя столбца в результирующем наборе.
Поскольку хранимые процедуры Informix и DB2 не имеют ассоциированных имён столбцов, не используйте этот метод для хранимых процедур этих БД.
close
Удаляет Resultset -объектobject.
next
Делает следующий ряд результирующего набора текущим рядом. Возвращает false, если текущий ряд является последним рядом результирующего набора; иначе возвращает true.
resultSet -объект является объектом "только для чтения"/read-only, объектом последовательного стиля/sequential-style. Исходя из этого, класс не имеет методов insertRow, deleteRow и updateRow, определённых для Cursor -объектов.
Методы Работы с Ошибками
Как уже было сказано, многие методы возвращают числовой статус-код. Если метод возвращает статус-код, может иметься и соответствующие код ошибки и сообщение от сервера БД. LiveWire имеет четыре метода для объектов Connection, DbPool и database для доступа к error-кодам и сообщениям БД.
Вот эти методы:
majorErrorMessage: наивысшее сообщение об ошибке, возвращённое базой данных.
minorErrorMessage: наименьшее сообщение об ошибке, возвращённое базой данных.
majorErrorCode: наивысший error-код, возвращённый БД. Обычно он соответствует SQLCODE сервера.
minorErrorCode: второй/secondary error-код, возвращённый базой данных.
Результаты, возвращаемые этими методами, зависят от используемого сервера БД и статус-кода БД. В большинстве случаев Вам нужно рассматривать только наивысший error-код или сообщение об ошибке, чтобы понять суть ошибки. Меньшие error-код и сообщение используются только в некоторых ситуациях.
ПРИМЕЧАНИЕ:
Вызов другого метода объектов Connection, DbPool или database может зачистить/reset error-коды и сообщения. Чтобы исключить потерю информации, не забудьте проверить эти методы, перед тем как продолжить.
После получения сообщения об ошибке ваше приложение может вывести сообщение пользователю. Ваше сообщение может включать строку, возвращённую majorErrorMessage или minorErrorMessage, или число, возвращённое majorErrorCode или minorErrorCode. Дополнительно можно обработать число или строку, перед тем как вывести их.
При обсчёте строки, возвращённой majorErrorMessage и minorErrorMessage, LiveWire возвращает строку поставщика БД с присоединённым дополнительным текстом. Детальную информацию о возвращаемых значениях см. в описаниях этих методов в книге Серверный JavaScript. Справочник.
Microsoft SQL Server (только для NT)
Прежде чем использовать нижеуказанные инструкции, Вы обязаны сконфигурировать Ваш Sybase-клиент, как указано в разделе Кроме того, в Unix установите DSQUERY так, чтобы она указывала на Ваш сервер.
SQL-файлы для создания видео-БД в MS SQL Server, находятся в двух директориях:
$NSHOME\js\samples\videoapp\mss $NSHOME\js\samples\oldvideo\mss
Из командной строки DOS запустите пакетный файл: mss_load userid password
Например:c:\netscape\server\js\samples\videoapp\mss\mss_load sa
Теперь можно запускать приложение, сделав изменения, описанные в разделе .
ПРИМЕЧАНИЕ:
Если у Вас на машине установлены и Sybase, и MS SQL Server или DB2, потенциально может возникнуть конфликт имён. Эти производители поставляют утилиты с одинаковыми названиями (bcp и isql). При запуске этих скриптов убедитесь, что переменная окружения настроена для запуска корректной утилиты.
MIME
Multipart Internet Mail Extension. Стандарт, специфицирующий формат данных, пересылаемых по internet.
Модифицирование Приложения Hello World
В этом разделе Вы модифицируете, рекомпилируете и рестартуете приложение-образец. Для редактирования исходного файла Вы сначала должны найти его. Как Вы помните, Application Manager показывает путь к исполняемому файлу приложения (файлу с расширением .web). Исходный файл hello.html должен находиться в той же директории. Отредактируйте файл. HTML-файл начинается такими операторами:
Hello World Hello World
Your IP address is write(request.ip);
write ("Last time you were " + client.oldname + ".");
This time you are write(request.newname);
client.oldname = request.newname;
Добавьте строку, выводящую тип пользовательского браузера:
You are using write(request.agent)
Если Вам нужно, можете также персонализировать шапку/head страницы; например, можете сделать такой заголовок: "Fred's Hello World."
Когда вы закончите изменение файла, запустите компилятор приложений JavaScript. В командной строке перейдите в директорию, содержащую исходный файл. Введите такую строку для компиляции приложения:
jsac -v -o hello.web hello.html
Альтернативно Вы можете из этой директории запустить скрипт build (в Unix) или build.bat (в NT). В этом случае компилятор стартует и выводит сообщения. Последнее сообщение должно быть "Compiled and linked successfully/Откомпилировано и скомпоновано успешно".
Опубликуйте файлы на Вашем сервере разработки. Для рестарта войдите в Application Manager, выберите Hello World, затем выберите Restart. Эта операция загрузит на сервер новую откомпилированную версию приложения. Затем Вы можете запустить приложение, выбрав Run. Открывается окно с Hello World. Вы увидите внесённые Вами изменения в приложении.
Модифицирование videoapp
Как способ применения функциональности LiveWire рассмотрим пример модернизации videoapp. Вот что можно сделать:
Изменить предположение о том, что существование массива sharedConnections предполагает наличие соединения у пользователя. Вы можете изменить start.htm, чтобы выполнять проверку наличия ID у данного пользователя в этом массиве и проверить, хранится ли соединение в нужном месте. См. раздел .
Это приложение никогда не возвращает соединения обратно в пул. Следовательно, если некоторое количество пользователей соединились, больше никто соединиться не сможет. Вы можете изменить это двумя путями: добавить новую команду, позволяющую пользователю указывать на завершение работы, или реализовать схему зачистки неиспользуемых соединений. См. .
Модификация Приложения
Чтобы модифицировать приложение, выберите имя приложения в списке приложений и щёлкните Modify.
Вы можете изменить любое поле, определённое при инсталяции приложения, за исключением имени приложения. Чтобы изменить имя приложения, необходимо удалить приложение, а затем реинсталировать его.
Если Вы модифицируете поля остановленного приложения, Application Manager автоматически запускает его. Если Вы модифицируете поля активного приложения, Application Manager автоматически останавливает и запускает его.
Навигация с Помощью Курсоров
Сначала указатель курсора позиционируется перед первым рядом виртуальной таблицы. Метод next используется для перемещения между записями виртуальной таблицы. Этот метод передвигает указатель на следующий ряд и возвращает true, когда следующий ряд виртуальной таблицы найден. Если следующего ряда нет, next возвращает false.
Например, предположим, что виртуальная таблица имеет столбцы с названиями title, rentalDate и dueDate. Следующий код использует next для итерации по рядам и отображения значений столбцов в таблице:
// Создаём курсор.
custs = connobj.cursor ("select * from customer");
// Проверяем курсор и отсутствие ошибок БД.
if ( custs && (connobj.majorErrorCode() == 0) ) {
write (""); // Итерация по рядам с отображением значений.
while (custs.next()) { write ("" + custs.title + " " + "" + custs.rentalDate + " " + "" + custs.dueDate + " "); }
write ("
");
// Всегда закрывайте курсоры по окончании работы!
custs.close();
}
Этот код даст на выходе:
Clockwork Orange
6/3/97
9/3/97
Philadelphia Story
8/1/97
8/5/97
Вы не всегда можете находиться в нужном месте в курсоре. Например, предположим, что Вы создаёте курсор и, пока Вы работаете с ним, кто-то добавляет ряд в таблицу. В зависимости от установок БД, этот ряд может появиться в Вашем курсоре. Исходя из этого, когда это удобно (как при обновлении рядов), Вы можете сделать так, чтобы Ваш код проверял, находится ли указатель в нужном ряду.
Несколько Результирующих Наборов
Хранимая процедура Sybase, Oracle, DB2 или ODBC может создавать несколько результирующих наборов. В этом случае хранимая процедура предоставляет один resultSet -объект для каждого набора.
Предположим, Ваша хранимая процедура выполняет такие операторы SQL: select name from customers where id = 6767 select * from orders where id = 6767
Вы можете использовать несколько resultSet -объектов, генерируемых этими операторами, таким образом:
// Этот оператор нужен для DB2, ODBC и Sybase.
poolobj.storedProcArgs("GetCustOrderInfo","IN");
spobj = connobj.storedProc("GetCustOrderInfo",6767);
if ( spobj && (connobj.majorErrorCode() == 0) ) {
resobj1 = spobj.resultSet();
// Перед тем как продолжить, убедитесь, что результирующий набор существует.
if ( resobj1 && (connobj.majorErrorCode() == 0) ) {
// Первый результирующий набор возвращает только один ряд.
// Убедитесь, что ряд содержит данные. rowexists = resobj1.next(); if ( rowexists )
write("Customer " + resobj1.name +
" has the following orders: "); resobj1.close();
// Второй результирующий набор возвращает один ряд для каждого заказа, // помещённого пользователем. Убедитесь, что ряды содержат данные.
resobj2 = spobj.resultSet(); var i = 0; if ( resobj2 && (connobj.majorErrorCode() == 0) ) { write("\nOrder# Quantity Total "); while(resobj2.next()) { write(resobj2.orderno + " " + resobj2.quantity + " " + resobj2.Totalamount + " ");
i++; } resobj2.close();
write("Customer has " + i + " orders. ");
} else write("Customer has no orders. "); } }
spobj.close();
В качестве примера использования нескольких ref-курсоров Oracle в хранимой процедуре см. описание класса Resultset в книге
Серверный JavaScript. Справочник.
Netscape cookie protocol/протокол кук Netscape
Netscape-формат специфицирования параметров кук в "шапках"/header HTTP.
Null-Значения
Когда Вы передаёте null JavaScript в качестве параметра Java-методам, Java конвертирует это значение в соответствии с правилами, описанными в таблице:
Тип Java-параметраПравила конвертации
Любой класс Любой тип интерфейса
Значение становится null.
byte char double float int long short
Значение становится 0.
boolean
Значение становится false.
О Конвертации Типов Данных
В БД имеется богатый набор типов данных. Машина выполнения JavaScript на сервере конвертирует эти типы данных в значения JavaScript, строки или числа. Число в JavaScript хранится как значение двойной точности с плавающей точкой. Вообще машина выполнения конвертирует символьные типы данных в строки, числовые типы данных - в числа, а даты - в Date -объекты JavaScript. Она также конвертирует null-значения в JavaScript null.
Примечание
Поскольку JavaScript не поддерживает фиксированные или упакованные десятеричные числа, возможна некоторая потеря точности при чтении и записи типов упакованных десятеричных данных. Проверьте результаты до вставки их обратно в БД и используйте соответствующие математические функции для коррекции потери точности.
О Приложениях-Образцах Серверного JavaScript
Если вы устанавливаете Netscape web-сервер, несколько примеров приложений JavaScript устанавливаются одновременно. Для получения представления о возможностях приложений JavaScript запустите их и просмотрите исходный код. Вы можете также изменять эти приложения по мере изучения возможностей JavaScript. Исходные и исполняемые файлы этих приложений установлены в директории $NSHOME\js\samples, где $NSHOME это директория, в которой Вы установили сервер.
В таблице перечислены приложения-образцы.
Базовые понятия
world Приложение "Hello World".
hangman "Виселица".
cipher Угадай цифру.
LiveWire Database Service
dbadminПростой интерактивный SQL-доступ с использованием LiveWire.
Если Вы имеете ограниченный доступ к Application Manager, это приложение также защищено именем и паролем администратора сервера.
videoapp Приложение видео-магазин, использующее реляционную БД видеоклипов.
oldvideo Альтернативная версия видео-магазина.
LiveConnect bugbase Пример БД "жучков" с использованием LiveConnect.
Другие приложения
sendmail Демонстрирует способность отправлять e-mail из вашего приложения JavaScript.
viewer Даёт возможность просматривать файлы на сервере, используя класс JavaScript File.
Из соображений безопасности это приложение не устанавливается автоматически вместе с Netscape-сервером. Если Вы его устанавливаете, ограничьте к нему доступ. Иначе неавторизованный пользователь сможет читать и записывать файлы на Вашем сервере. Об ограничении доступа к приложению см. руководство администратора Вашего web-сервера.
jsaccall Пример использования внешних библиотек и предоставления доступа к CGI-переменным.
1
Эти приложения работают только при наличии поддерживаемого сервера БД, установленного в сети, и корректно сконфигурированного клиентского программного обеспечения. См. . Перед началом использования videoapp или oldvideo выполните указания по их установке.
ПРИМЕЧАНИЕ:
Помимо указанных, в директории $NSHOME\js\samples имеется также приложение metadata. Оно используется Visual JavaScript. Когда Вы будете просматривать исходный код, не изменяйте исполняемый файл.
Остаток этой главы посвящён двум простым приложениям, которые дадут Вам возможность поработать с приложениями JavaScript. Не беспокойтесь о деталях. Это обсуждение предназначается только для того, чтобы показать Вам возможности приложений JavaScript. Детали обсуждаются далее в этой главе.
В , приложение videoapp рассматривается детально. Вы должны прочесть эту главу перед началом работы с LiveWire Database Service.
О Приложениях Videoapp и Oldvideo
Netscape-серверы поставляются с двумя приложениями-образцами для работы с базами данных, videoapp и oldvideo, которые иллюстрируют работу LiveWire Database Service. Эти приложения весьма похожи; они отслеживают прокат видео в воображаемом видео-салоне. Приложение videoapp демонстрирует использование объектов DbPool и Connection. Приложение oldvideo демонстрирует использование предопределённого объекта database.
Есть несколько небольших ограничений на использование этих приложений:
Приложение videoapp не может базироваться на БД Informix. Приложение oldvideo может использоваться с Informix. Поскольку эти приложения могут использоваться с ODBC и SQL Server, если драйвер на Вашей платформе не поддерживает обновляемые курсоры, приложения работать не будут. О том, какие драйверы поддерживают обновляемые курсоры, см. раздел .
Приложение videoapp использует курсоры, захватывающие несколько HTML-страниц. Если ваш драйвер БД - однопоточный, эти курсоры могут иметь блокировки для БД и препятствовать доступу к ним других пользователей.
О том, какие драйверы являются однопоточными, см. .
О Сервисе CORBA
Netscape Internet Service Broker for Java (ISB for Java) это брокер запроса объектов фирмы Netscape. ISB for Java устанавливает соединения внутри себя и с другими брокерами запроса объектов/object request brokers (ORB) путём использования протокола Internet InterORB Protocol (IIOP).
ISB for Java даёт Вашим приложениям JavaScript доступ к распределённой объектной модели CORBA, опубликованной в ORB, работающем на основе IIOP (включая сам ISB for Java). Эти объекты могут быть частью распределённого приложения. Чтобы получить доступ к такому распределённому объекту, Вы обязаны иметь Java-stub/основу, и этот stub-класс обязан быть в пути Вашей CLASSPATH. В свою очередь, Вы можете использовать Java и LiveConnect для экспонирования частей Вашего серверного приложения JavaScript как распределённых объектов CORBA.
За пределами данного учебника остаётся описание создания CORBA-исполняемых распределённых объектов с использованием ISB for Java, а также то, как делать Java-стабы для таких объектов. Об этом см. учебник .
Приложения серверного JavaScript могут получать доступ к распределённому объекту в зависимости от того как он опубликован. Простейшей альтернативой является создание и запуск распределённого объекта как отдельного процесса, что показано на следующем рисунке.
Рисунок 22.1 Приложение JavaScript CORBA-клиент
Как видно на рисунке, среды запуска Java и JavaScript находятся вместе на одном web-сервере. Они взаимодействуют путём использования LiveConnect стандартным способом, описанным ранее в этой главе. Методы, вызываемые в оболочке стаба в JavaScript, дают в результате вызов методов объекта Java-стаба в Java. Стаб использует Java ORB для взаимодействия с удалённым сервисом. В данной архитектуре серверный процесс объекта может проходить только на машине, которая имеет ORB, и может быть написан на любом языке.
Приложение-образец flexi иллюстрирует это. В нём FlexiServer это отдельное приложение Java, содержащее реализации нескольких распределённых объектов. Этот пример обсуждается в разделе .
После того как поработаете с flexi, прочтите в разделе обсуждение более сложных альтернатив публикации.
О Службе LiveWire Database Service
Одновременно с версиями 3.x и 4.x Netscape-серверов Вы обязаны установить клиентскую библиотеку БД (и к тому же - определённую версию), если хотите использовать LiveWire Database Service. Вы также обязаны сконфигурировать эту клиентскую библиотеку для работы с LiveWire.
Netscape-серверы не поставляются вместе клиентскими библиотеками БД. Вам нужно связаться с поставщиком Вашей БД на предмет получения соответствующей библиотеки. Вам необходимо установить и сконфигурировать клиентские библиотеки только тех БД, которые Вы будете использовать.
Если Вы устанавливаете БД на другую машину (не на ту, где установлен web-сервер), Вы обязаны иметь установленную клиентскую библиотеку БД на машине с web-сервером. Вы обязаны получить соответствующее лицензионное разрешение от поставщика Вашей БД. Netscape не сделает это за Вас.
Требования по конфигурированию Вашей БД могут отличаться в зависимости от того, находятся ли БД и web-сервер на одной или на разных машинах. Если они на одной машине, последующая информация будет касаться локальной конфигурации; если на разных машинах - удалённой конфигурации.
В этой главе рассмотрены только те аспекты установки клиента БД, которые имеют отношение к использованию с LiveWire. Для получения общей информации об установке клиента БД обратитесь к соответствующей документации поставщика БД.
Объект client
Несколько браузеров-клиентов могут иметь одновременный доступ к приложению JavaScript. Объект client предоставляет метод для работы отдельно с каждым клиентом. Он также имеет технологию для отслеживания работы каждого браузера-клиента с приложением при наличии нескольких запросов.
Машина выполнения JavaScript на сервере конструирует объект client для каждой пары клиент/приложение. Браузер-клиент, соединённый с одним приложением, имеет другой объект client из того же самого браузера-клиента, соединённого с другим приложением. Машина выполнения конструирует новый объект client каждый раз, когда пользователь выполняет доступ к приложению; могут быть сотни и тысячи объектов client, активных одновременно.
ПРИМЕЧАНИЕ:
Вы не можете использовать объект client на начальной странице Вашего приложения. Эта страница начинает работу при старте приложения на сервере. В этот момент клиентского запроса нет, и поэтому нет также и доступного объекта client. Дополнительно см. раздел .
Машина выполнения конструирует и уничтожает объект client
для каждого клиентского запроса. В то же время, при обработке запроса машина выполнения сохраняет имена и значения свойств объекта client. Таким способом машина выполнения может конструировать новый объект client из сохранённых данных, если тот же самый пользователь вновь использует приложение, сделав следующий запрос. Таким образом, концептуально Вы можете представлять объект client как объект, действующий в течение сессии работы клиента с приложением.
JavaScript не сохраняет объекты client, не имеющие значений свойств. Поэтому, если приложению не нужны объекты client и оно не присваивает свойствам объекта client никаких значений, оно не выполняет никакой лишней работы.
У Вас имеются несколько различных опций: как и где машине выполнения сохранять свойства объекта client. Эти опции обсуждаются в разделе .
Резюме по объекту client см. в разделе .
Объект Packages
Если класс Java не является частью пакетов java, sun или netscape, Вы имеете к нему доступ через объект Packages. Например, корпорация Redwood использует пакет Java под названием redwood как контейнер различных Java-классов, которые ею реализованы. Для создания экземпляра класса HelloWorld в redwood Вы вводите конструктор класса:
var red = new Packages.redwood.HelloWorld()
Вы можете также получить доступ к классам в пакете по умолчанию (то есть классам, которые не указывают пакет явно). Например, если класс HelloWorld находится непосредственно в CLASSPATH, а не в пакете, Вы можете получить к нему доступ так:
var red = new Packages.HelloWorld()
Объекты LiveConnect java, sun и netscape являются сокращениями для обычно используемых пакетов Java. Например, можно записать так:
var myString = new java.lang.String("Hello world")
вместо более длинной версии:
var myString = new Packages.java.lang.String("Hello world")
По умолчанию директория $NSHOME\js\samples, где $NSHOME это директория, в которой установлен сервер, находится в CLASSPATH сервера. Вы можете поместить Ваш пакет в эту директорию. Альтернативно Вы можете поместить Ваши пакеты и классы Java в другую директорию. Если Вы это делаете, убедитесь, что директория находится в Вашем CLASSPATH.
Объект project
Объект project содержит глобальные данные приложения и предоставляет метод для совместного использования информации клиентами, выполняющими доступ к приложению. JavaScript конструирует новый объект project, когда приложение стартует при использовании Application Manager. Каждый клиент, получающий доступ к приложению, использует один и тот же объект project. Резюме по объекту project см. в разделе .
В отличие от предыдущих релизов, в этом релизе машина выполнения JavaScript не создаёт и не уничтожает объект project для каждого запроса. Если Вы остановили работу приложения, объект project этого приложения уничтожается. Новый объект project создаётся для приложения, когда оно стартует снова. Типичный период существования объекта project - дни или недели.
JavaScript конструирует набор объектов project для каждого Netscape HTTP-процесса, запущенного на сервере. JavaScript конструирует объект project для каждого приложения, запущенного на каждом отдельном сервере. Например, если один сервер запущен на порте 80, а другой - на порте 142 на той же самой машине, JavaScript конструирует отдельный набор объектов project для каждого процесса.
Объект request
Объект request содержит данные, специфичные для текущего клиентского запроса. Они имеет самое короткое время существования из всех объектов. JavaScript конструирует новый объект request для каждого получаемого клиентского запроса; например, объект создаётся, когда
Пользователь вручную запрашивает URL путём его ввода или выбора закладки/bookmark.
Пользователь щёлкает гиперссылку или иным способом запрашивает документ, относящийся к другой странице.Клиентский JavaScript устанавливает свойство document.location или переходит к странице, используя метод history.
Серверный JavaScript вызывает функцию redirect.
Машина выполнения JavaScript на сервере уничтожает объект request по окончании ответа на запрос (обычно предоставляя запрошенную страницу). Следовательно, типичный период существования объекта request - менее одной секунды.
ПРИМЕЧАНИЕ:
Вы не можете использовать объект request в начальной странице приложения. Эта страница запускается, когда приложение стартует на сервере. В этой точке нет объекта клиентского запроса, и поэтому нет доступного объекта request. О начальных страницах см. раздел .
Резюме по объекту request см. а разделе .
Объект server
Объект server содержит глобальные данные для всего сервера в целом и предоставляет метод для обеспечения совместного использования информации разными приложениями, работающими на сервере. Объект server также автоматически инициализируется информацией о сервере. Резюме по объекту server см. в разделе .
Машина выполнения JavaScript конструирует новый объект server, когда сервер стартует, и уничтожает объект server, когда сервер останавливается. Каждое приложение, запущенное на сервере, использует один и тот же объект server.
JavaScript конструирует объект server для каждого Netscape HTTPD-процесса (на сервере), запущенного на машине. Например, может иметься серверный процесс на порте 80 и другой - на порте 8080. Это совершенно отдельные серверные процессы, и JavaScript конструирует объект server для каждого из них.
Объект
Если метод возвращает объект, он может быть либо реальным объектом, либо null. Если метод возвращает null, возможно, возникла ошибка JavaScript. В большинстве случаев, если ошибка возникла в БД, метод возвращает верный объект, но программа устанавливает код ошибки.
Глобальная функция blob возвращает объект. Кроме того, следующие методы также возвращают объект:
Connection.cursor Connection.storedProc database.cursor
database.storedProc DbPool (constructor) DbPool.connection Stproc.resultSet
Создаёте ли Вы курсор, результирующий набор или хранимую процедуру, Вы должны проверять и существование созданного объекта, и возможное наличие кода ошибки. Вы можете использовать методы majorErrorCode и majorErrorMessage для тестирования ошибки.
Например, Вы можете создать курсор и проверить его корректность кодом такого вида:
// Создаётся Cursor-объект. custs = connobj.cursor ("select id, name, city
from customer order by id");// Прежде чем продолжить, убедитесь, что возвращён реальный курсор // и что нет ошибки БД.
if ( custs && (connobj.majorErrorCode() == 0) ) {
// Получить первый ряд.
custs.next();
// ... процессинг рядов курсора ... //Закрыть курсор. custs.close(); }
else // ... обработка ошибок ...
Объекты JavaArray и JavaObject
В большинстве случаев, когда Вы передаёте объект JavaScript JavaArray или JavaObject как параметр Java-методу, Java просто разворачивает этот объект (снимает оболочку); иногда объект переводится в другой тип данных по правилам из таблицы:
Тип Java-параметраПравила конвертации
Любой интерфейс или класс, который совместим в операции присвоения с развёрнутым объектом.
Оболочка с объекта снимается.
java.lang.String
Оболочка с объекта снимается, вызывается метод toStringразвёрнутого Java-объекта, а результат возвращается как новый экземпляр java.lang.String.
byte char double float int long short
Оболочка с объекта снимается, и возникает одна из следующих ситуаций:
Если развёрнутый Java-объект имеет метод doubleValue, JavaArray или JavaObject конвертируется в значение, возвращаемой этим методом.
Если развёрнутый Java-объект не имеет метода doubleValue, возникает ошибка.
boolean
Оболочка с объекта снимается, и возникает одна из следующих ситуаций:
Если развёрнутый объект имеет метод booleanValue, объект-источник конвертируется в это return-значение.
Если развёрнутый объект не имеет метода booleanValue, конвертация терпит неудачу.
Интерфейс или класс совместимы для присвоения с развёрнутым объектом, если развёрнутый объект является экземпляром типа Java-параметра. То есть, следующий оператор обязан возвращать true:
развёрнутыйОбъект instanceof типПараметра
Объекты JavaClass
Если вы передаёте JavaScript-объект JavaClass в качестве параметра Java-методу, Java конвертирует объект в соответствии с правилами из таблицы:
Тип Java-параметраПравила конвертации
java.lang.Class
Оболочка с объекта снимается.
java.lang.JSObject java.lang.Object
Объект JavaClass оборачивается в новый экземпляр java.lang.JSObject.
java.lang.String
Оболочка с объекта снимается, вызывается метод toString развёрнутого Java-объекта, а результат возвращается как новый экземпляр java.lang.String.
boolean
Оболочка с объекта снимается, и возникает одна из следующих ситуаций:
Если развёрнутый объект имеет метод booleanValue, исходный объект конвертируется в return-значение.
Если объект не имеет метода booleanValue, конвертация терпит неудачу.
Обмен Информацией
Работа хранимых процедур имеет отличия на разных БД, поддерживаемых сервисом LiveWire Database Service. Самое важное для LiveWire - это отличия в передаче информации в и из хранимой процедуры в приложении на JavaScript. Вы всегда используете параметры ввода хранимой процедуры для передачи информации в хранимую процедуру.
Концептуально имеются несколько способов, которыми можно запросить информацию из хранимой процедуры. Не всегда производитель БД даёт возможность запрашивать информацию любым их этих способов.
Обновление Предыдущей Версии
Если у вас имеется установленная версия предыдущего релиза Netscape web-сервера, Вы должны перенести установки сервера при инсталяции Enterprise Server 4.x. См. Enterprise Server 4.0 Installation and Migration Guide.
Если Вы ранее создавали приложения JavaScript, используя Серверный JavaScript 3.x, Вы должны знать об изменениях, выполняемых при обновлении до версии 4.x и переносе старых установок сервера:
Если предыдущий сервер имел включённую службу LiveWire, сервер 3.x будет иметь включённый JavaScript. Требование (или отсутствие) Application Manager'ом пароля также сохраняется. См. также раздел в .
Обновление установок сервера не переносит ваших приложений, а также не рекомпилирует их для использования с сервером 4.x. Вы обязаны вручную рекомпилировать пользовательские приложения перед тем как использовать их с сервером 4.x, как указано в разделе . Вы должны знать, что старые приложения могут перестать работать с их оригинальными версиями Enterprise Server после рекомпиляции. Если Вы хотите использовать приложения с обоими серверами, Вы должны скопировать приложение, а не перемещать его.Об изменениях, которые, возможно, понадобиться сделать в коде при обновлении, см. следующий раздел.
Обработка Исключений JavaScript в Java
Если JavaScript-код, вызванный из Java, потерпел неудачу на этапе прогона/выполнения, он вызывает исключение. Если Вы вызываете JavaScript-код из Java, Вы можете отловить/catch это исключение в блоке операторов try...catch. Исключение JavaScript доступно коду Java как экземпляр netscape.javascript.JSException. JSException это Java-оболочка вокруг исключения любого типа, вызываемого в JavaScript, так же как и экземпляры JSObject являются оболочками для JavaScript-объектов.
Используйте JSException при вычислении JavaScript-кода в Java. Если JavaScript-код не вычисляется из-за ошибки компиляции JavaScript или из-за какой-то другой ошибки времени прогона, интерпретатор JavaScript генерирует сообщение об ошибке, которое конвертируется в экземпляр JSException.
Например, можно использовать блок try...catch для обработки исключений LiveConnect:
try { global.eval("foo.bar = 999;");
} catch (Exception e) { if (e instanceof JSException) {
jsCodeFailed()"; } else {
otherCodeFailed(); } }
В этом примере оператор eval терпит неудачу, если foo не определён. Блок catch выполняет метод jsCodeFailed, если оператор eval в блоке try вызывает JSException; метод otherCodeFailed выполняется, если блок try вызывает какую-то иную ошибку.
Обработка Ошибок в Серверном JavaScript
Функция ssjs_onError, если она определена в Вашем приложении, вызывается в случае ошибки серверного JavaScript, такой как "undefined variable name/имя переменной не определено". В функции ssjs_onError Вы можете делать всё, что можно делать в функции серверного JavaScript, включая доступ к объектам server, project, client и request. Вы можете также выполнять перенаправление и вызывать другие функции.
Функция ssjs_onError имеет следующий синтаксис:
function ssjs_onError (,,)
текст сообщения об ошибке
имя исходного файла
номер строки с ошибкой
Ошибка JavaScript в ходе выполнения функции onError записывается в log-файл и трассируется (если активна). Функция ssjs_onError, однако, не вызывается рекурсивно. Ошибка в функции onError вызывает запись сообщения в error log, но не выполняет вызов onError.
Вот пример функции:
function ssjs_onError(msg,file,line) { write(" \n ")
write("error message: "+msg+" \n")
write("file name: "+file+" \n")
write("line number: "+line+" \n")
write(" ") }
ПРИМЕЧАНИЕ:
Чтобы дать каждой странице её собственную специальную функцию onError, добавьте присвоение ssjs_onError в начале кода страницы. Например:
ssjs_onError = custom_onError;
function custom_onError(msg,file,line) {
// ... }
Серверный JavaScript выполняет всё, что ssjs_onError представляет во время ошибки. Вы можете использовать одну функцию ssjs_onError, которая совместно используется всеми страницами, либо можете динамически переключаться на другую функцию onError в любое время, в том числе в начале каждой страницы. Если два запроса выполняют одну и ту же функцию onError в один момент времени, они имеют различные среды выполнения, как если бы Вы одновременно выполняли какую-нибудь другую функцию.
| | |
Обратная Совместимость с Предыдущими Релизами
Вы также должны знать об изменениях в поведении приложений серверного JavaScript по сравнению с Netscape Enterprise Server 3.x:
Вы обязаны рекомпилировать все ваши существующие приложения JavaScript. об использовании компилятора см. . После рекомпиляции приложений они больше не будут работать под старыми инсталяциями SSJS.
Обратные Кавычки
Используйте обратные кавычки (`) для выделения выражений серверного JavaScript как заместителей для имён атрибутов или значений атрибутов HTML. JavaScript, внедрённый в HTML с помощью обратных кавычек, автоматически генерирует HTML; Вам не нужно использовать write.
В целом тэги HTML имеют форму:
где ATTRIB это атрибут, а "value
" это его значение. Значение в угловых скобках означает, что допускается любое количество пар атрибут/значение.
Если в обратные кавычки заключено выражение JavaScript, используемое как значение атрибута, машина выполнения JavaScript автоматически добавляет знак кавычки вокруг всего значения. Вы сами не вводите знаки кавычек, хотя Вам это может понадобиться для разграничения строковых литералов выражения, как в следующем примере. Машина выполнения не делает это для имён атрибутов, поскольку не предполагается заключение имён атрибутов в кавычки.
Например, рассмотри следующую строку из образца-приложения Hangman:
Эта строка динамически генерирует имя изображения на основе значения client.num_misses. Обратные кавычки обрамляют выражение JavaScript, конкатенирующее строку "images\hang" и целочисленное значение client.num_misses и строку ".gif", давая строку типа "images\hang0.gif". Результатом будет HTML, такой как
Порядок ввода кавычек является критичным. Сначала идёт обратная кавычка, указывая, что следующее значение является выражением JavaScript, состоящим из строки ("images\hang"), соединяемой с целым числом (client.num_misses) и с другой строкой (".gif"). JavaScript конвертирует всё выражение до строки и добавляет необходимые знаки кавычек вокруг значения атрибута.
Вы должны внимательно использовать знаки двойных кавычек внутри обратных кавычек, поскольку содержащееся внутри них значение интерпретируется как литерал. Поэтому не окружайте выражения JavaScript, которые необходимо вычислить, знаками кавычек. Например, если значение свойства client.val будет NetHead, то данный оператор:
генерирует такой HTML:
но следующий оператор:
генерирует HTML:
В качестве другого примера приведём два атрибута тэга ANCHOR - HREF и NAME. HREF делает тэг гиперссылкой, а NAME делает его именованным якорем. Следующие операторы используют переменную choice для установки свойств attrib и val объекта client и создают затем гиперссылку/hyperlink или цель/target, в зависимости от значений:
if (choice == "link") { client.attrib = "HREF"; client.val = "http://www.netscape.com"; } if (choice == "target") {
client.attrib = "NAME"; client.val = "NetHead"; }
Netscape Communications
Если значением choice будет "link", результат будет:
Netscape Communications
Если значением choice будет "target", результат будет:
Netscape Communications
Обслуживание Пулов Соединений
В любой данный момент времени соединённый объект DbPool или database и все соединения пула ассоциированы с определённой конфигурацией базы данных. То есть всё, что находится в пуле, соединено с определённым сервером БД как отдельный пользователь с отдельным паролем и с определённой БД.
Если Ваше приложение всегда использует одну конфигурацию, то можно использовать единственный объект DbPool или использовать объект database и соединяться однократно. В этом случае Вы должны выполнить соединение на начальной странице Вашего приложения.
Если Вашему приложению требуется несколько конфигураций, или потому что оно обязано соединяться с несколькими БД, или с одной БД, но с разными пользователями, или и то, и другое, Вам необходимо определить, как обслуживать эти конфигурации.
Если Вы используете объект database и несколько соединений, то выбора у Вас нет. Вы обязаны соединяться, отсоединяться и повторно соединяться с объектом database каждый раз, когда Вам нужно изменить что-либо в конфигурации. Вы делаете это под управлением клиентских запросов. В этой ситуации убедитесь, что используются блокировки, как указано в разделе чтобы получать исключительный доступ к объекту database. Иначе другой клиентский запрос может отключить объект до того, как текущий клиентский запрос закончит с ним работу. Хотя Вы и можете использовать объект database таким образом, лучше будет всё-таки использовать объекты DbPool.
Если Вы используете объекты DbPool и несколько конфигураций, Вы также должны соединяться, отсоединяться и повторно соединяться с объектом DbPool. Однако с объектами DbPool у Вас появится больше возможностей. Вы можете создавать столько пулов, сколько нужно, и ставить их под контроль объекта project. (См. в информацию об объекте project.) Использование нескольких пулов более эффективно и обычно надёжнее, чем многократное использование единственного пула (как с объектом database , так и с единственным объектом DbPool).
При определении того, как обслуживать пулы, Вы обязаны учитывать два фактора: ко скольки конфигурациям будут иметь доступ пулы и нужно ли будет одному соединению захватывать несколько клиентских запросов. Если у Вас небольшое количество возможных конфигураций, Вы можете создать отдельные пулы для каждой. В разделе обсуждается этот подход.
Если у Вас имеется очень большое или заранее не известное количество конфигураций (например, если все пользователи БД получают свои индивидуальные ID), нужно предусмотреть два варианта. Если одного соединения достаточно для выполнения одного клиентского запроса, Вы можете создавать отдельные пулы на клиентской странице.
Однако иногда соединение должно захватывать несколько клиентских запросов (например, если одна транзакция в БД захватывает несколько клиентских запросов). Возможно также, что Вы просто не хотите повторно соединяться с БД на каждой странице приложения. Если это так, Вы можете создать массив пулов, который используется совместно. В разделе обсуждается этот подход.
Независимо от используемого подхода, если Вам больше не нужно отдельное соединение в пуле, зачистите ресурсы, используемые этим соединением, чтобы оно стало доступным для других пользователей. Чтобы выполнить это, закройте все открытые курсоры, хранимые процедуры и результирующие наборы. Верните соединение обратно в пул. (Вы не должны освобождать соединение, если используете объект database.)
Если Вы не освободили соединение, то при попытке отсоединить пул система будет ожидать, перед тем как реально отсоединиться, возникновения одного из двух условий:
Вы освобождаете все соединения
Соединения выходят за пределы области видимости и убираются сборщиком мусора
Если Вы создаёте отдельные пулы БД для каждого пользователя, убедитесь, что пул отсоединён, до того как закончить с ним работу. О курсорах см . О хранимых процедурах и результирующих наборах см. .
Обслуживание Соединения по Нескольким Запросам
В некоторых случаях может понадобиться, чтобы единственное соединение захватывало несколько клиентских запросов. То есть Вы сможете использовать одно соединение на нескольких страницах HTML.
Обычно вы используете свойства объекта client для информации, захватывающего клиентские запросы. Однако значение свойства объекта client не может быть объектом. Исходя из этого, Вы не можете сохранять пул соединений БД в объекте client. Вместо этого Вы используете пул соединений, хранимый в объекте project, обслуживая их так, как описано в данном разделе. Если вы используете этот подход, Вам может понадобиться кодирование пользовательской информации, по соображениям безопасности.
ПРЕДУПРЕЖДЕНИЕ!
Будьте особенно осторожны при использовании такого подхода, поскольку сохранение соединения таким способом делает его недоступным для других пользователей. Если все соединения окажутся недоступны, новые запросы будут ожидать явного освобождения соединения или таймаута соединения. Это особенно проблематично для однопоточных библиотек БД. (Об установлении соединений так, что они будут запрашиваться, если не заняты в течение продолжительного времени, см. ).
В следующем примере соединение и транзакция захватывают несколько клиентских запросов. Код сохраняет соединение как свойство объекта sharedConns, который сам является свойством объекта project. Объект sharedConns не является предопределённым объектом JavaScript. Он просто создан в данном примере и может иметь другое имя, по Вашему выбору.
Поскольку один пул используется всеми клиентами, Вы должны создавать объект sharedConns и создавать и соединять сам пул на начальной странице приложения примерно таким кодом:
project.sharedConns = new Object(); project.sharedConns.conns = new Object(); project.sharedConns.pool = new DbPool ("SYBASE", "sybaseserver", "user", "password", "sybdb", 10, false);
Затем на первой клиентской странице, получающей доступ к пулу, следуйте такой стратегии:
// Генерируется уникальный индекс для обращения к данному клиенту, если он ещё // не сгенерирован на другой странице. if client.id == null { client.id = ssjs_generateClientID(); }// Для удобства устанавливается переменная для данного пула. var clientPool = project.sharedConns.pool;// Проверяется, соединён ли пул. Если нет, перенаправляется // на специальную страницу для информирования пользователя. project.lock(); if (!clientPool.connected()) { delete project.sharedConns.pool; project.unlock(); redirect("noconnection.htm"); } project.unlock();// Соединение получается из пула и сохраняется в объекте project. project.sharedConns.conns[client.id] = clientPool.connection(); var clientConn = project.sharedConns.conns[client.id];
clientConn.beginTransaction(); cursor = clientConn.cursor("select * from customers", true"); // ... другие операции с БД ... cursor.close();
}
Заметьте, что эта страница не выполняет откат или подтверждение транзакции. Соединение остаётся открытым, и транзакция продолжается. (Транзакции рассматриваются в разделе ).
Вторая HTML-страница запрашивает соединение, базируясь на значении client.id, и продолжает работать с БД так:
// Запрашивается соединение. var clientConn = project.sharedConns.conns[client.id];
// ... Выполняются ещё какие-нибудь операции с БД ... // Здесь, если операции с БД успешно прошли, okay устанавливается в 1.
// Если была ошибка при работе с БД, okay устанавливается в 0. В конце // подтверждается или откатывается транзакция на основе этого значения.
if (okay)
clientConn.commitTransaction(); else clientConn.rollbackTransaction();
// Соединение возвращается в пул.
clientConn.release();
// Избавляемся от значения свойства объекта. Оно Вам больше не нужно.
delete project.sharedConns.conns[client.id];
В этом примере объект sharedConns сохраняет единственный объект DbPool и соединения для данного пула, которые используются в данный момент. Ситуация может быть значительно сложнее. Если у Вас имеется фиксированный набор пулов БД, Вы можете определить отдельный объект для хранения соединений каждого пула. Если у вас имеется массив пулов и каждому пулу необходимы соединения, захватывающие несколько запросов, Вам необходимо создать массив объектов, каждый из которых сохраняет пул и массив его соединений. Как ответвление, вместо немедленного перенаправления в том случае, если пул не соединён, клиентская страница может сделать новую попытку установить соединение.
Если Вы используете ssjs_generateClientID и храните ID в объекте client, Вам понадобится защита от вторжения и получения доступа к ID и, следовательно, к закрытой информации.
Обслуживание Транзакций
Транзакция это несколько действий с базой данных, выполняемых вместе. Либо все эти действия выполняются успешно, либо все вместе терпят неудачу. Если эти действия выполняют (окончательно) изменения БД, говорится, что транзакция подтверждена. Вы можете также выполнить откат /roll back транзакции, т.е. не подтвердить её; это отменяет все выполненные действия.
Транзакции важны для поддержания целостности и структуры данных. В то время как различные серверы БД реализуют механизм транзакций с некоторыми отличиями, сервис LiveWire Database Service предоставляет одни и те же методы для обслуживания транзакций на всех БД. Проверьте в документации продавца БД информацию о согласованности данных и уровнях изоляции транзакций.
Вы можете использовать явный контроль транзакции над выполнением любого набора действий. Например, акции, модифицирующие БД, должны проходить под управлением транзакций. Это акции, соответствующие операторам SQL INSERT, UPDATE и DELETE. Транзакции могут также использоваться для контролирования согласованности данных.
Для большинства БД, если Вы не выполняете явного управления транзакциями, машина выполнения использует фоновый механизм БД - autocommit/автоподтверждение, когда каждый оператор в БД рассматривается как отдельная транзакция. Каждый оператор подтверждается или откатывается немедленно на основе успеха или неуспеха выполнения каждого отдельного оператора. Явное управление транзакциями переопределяет работу этого механизма по умолчанию.
В некоторых БД, таких как Oracle, autocommit это явный механизм, который LiveWire включает для каждого отдельного оператора. В других БД, таких как Informix, autocommit это поведение по умолчанию, если Вы не создаёте транзакцию. В общем, LiveWire скрывает эти различия и переводит приложение в режим autocommit, если приложение не использует beginTransaction для явного старта транзакции.
Для ANSI-БД Informix, LiveWire не использует autocommit. Для этих БД приложение всегда использует транзакции, даже если никогда явно не вызывает beginTransaction. Приложение обязано использовать commitTransaction или rollbackTransaction для завершения транзакции.
ПРИМЕЧАНИЕ:
Настоятельно советуем всегда использовать явный контроль транзакций при выполнении изменений в БД. Это гарантирует, что изменения будут сделаны или отменены вместе. Кроме того, при использовании обновляемых курсоров Вы также всегда должны использовать явные транзакции для контроля за целостностью Ваших данных в период между чтением данных (с помощью next) и их изменением (с помощью insertRow, updateRow или deleteRow).
Как указано в разделе , использование явного контроля транзакций и обновляемых курсоров необходимо для того, чтобы исключить ошибки в некоторых БД, таких как Oracle и Informix.
fields are required for the
Add a New Customer
Note: All fields are required for the new customer
2
Jane Doe
Cupertino
3
John Brown
Harper's Ferry
В примере использованы методы, обсуждаемые в последующих разделах.
Отправка Значений с Клиента на Сервер
Есть несколько способов отправки информации с клиента на сервер:
Машина выполнения автоматически создаёт свойства объекта request для каждого значения в HTML-форме. (См. ) .
Если Вы используете основанную на URL технику обслуживания свойств объекта client, Вы можете модифицировать URL, отправленный серверу, чтобы включить значения свойств объектов client и request. (См. ) .
Вы можете использовать куки для установки значений свойств объектов client и request. (См. ) .
На стороне клиента Вы можете модифицировать шапку/header клиентского запроса. Вы можете затем использовать метод httpHeader объекта request для манипулирования шапкой и, возможно, телом запроса. (См. ).
Отправка Значений с Сервера Клиенту
Приложение JavaScript сообщается с клиентом через HTML и клиентский JavaScript. Если Вам нужно просто вывести информацию пользователю, нет никаких проблем: Вы создаёте HTML для форматирования этой информации так, как она будет отображаться.
Однако Вам может понадобиться выслать значения непосредственно клиентскому скрипту. Можно сделать это по-разному, включая такие способы:
Вы можете установить значения по умолчанию формы и значения для скрытых/невидимых элементов формы. (См. ).
Вы можете непосредственно заменить информацию в клиентских операторах SCRIPT или обработчиках событий. (См. ) .
Вы можете использовать куки для отправки значений свойств объекта client или других значений клиенту. (См. ) .
Вы можете изменить шапку/header ответа, высылаемую клиенту, используя функции deleteResponseHeader и addResponseHeader. (См. ).
Ожидание Соединения
В пуле, созданном объектом DbPool, соединений имеется фиксированное количество соединений. Если в момент попытки доступа все соединения заняты, Ваше приложение ожидает освобождения соединения в течение специфицированного периода таймаута. Вы можете управлять периодом ожидания.
Предположим, Вы определили следующий пул из 3 соединений:
pool = new DbPool ("ORACLE", "myserv", "user", "password", "", 3);
Предположим далее, что три клиента одновременно получают доступ к приложению и каждый использует одно из трёх соединений. Четвёртый клиент теперь запрашивает соединение через следующий вызов:
myconnection = pool.connection();
Этот клиент обязан ждать, пока один из трёх клиентов не освободит соединение. В данном случае, поскольку вызов connection не специфицирует таймаут, клиент ждёт освобождения соединения неопределённо долго, а затем возвращает это соединение.
Вы можете специфицировать различные периоды таймаута, задавая аргументы метода connection. Второй аргумент метода connection это период таймаута в секундах. Если Вы специфицируете таймаут 0, система ждёт бесконечно долго. Например, следующий код ожидает соединения только 30 секунд перед таймаутом:
myconnection = pool.connection ("Name of Connection", 30);
Если в течение специфицированного периода соединение не освобождается, метод возвращает null, и в сообщение об ошибке устанавливается сообщение о наименьшей ошибке. Вы можете получить это сообщение, вызвав метод minorErrorMessage объекта pool. Если Вы вызываете таймаут из connection, Вам может понадобиться освободить соединение, отключив одно из уже установленных. Дополнительно см. .
Параметры Вывода и Ввода/Вывода
Помимо стандартных параметров ввода, некоторые производители БД разрешают вводить другие типы параметров для хранимых процедур. Параметры вывода хранят информацию при возвращении из хранимой процедуры и параметры ввода/вывода, передающие и возвращающие информацию.
Для большинства БД Вы используете методы outParamCount и outParameters класса Stproc для доступа к параметрам вывода и ввода/вывода. Informix, однако, не разрешает параметры вывода и ввода/вывода. Соответственно, Вы не должны использовать методы outParamCount и outParameters с хранимыми процедурами Informix.
Переход к Новому Клиентскому Запросу
Функция redirect прерывает текущий клиентский запрос и стартует новый по специфицированному URL. Например, у вас имеется оператор:
redirect("http://www.royalairways.com/apps/page2.html");
Когда машина выполняет это оператор, она прерывает текущий запрос. Машина выполнения не продолжает обработку страницы-оригинала. Следовательно любые операторы HTML или JavaScript, идущие в оригинальной странице после вызова redirect, будут утеряны. Клиент сразу загрузит указанную страницу, отбросив предыдущее содержимое.
Параметром для redirect может быть любой оператор серверного JavaScript, вычисляемый до URL. Таким образом, Вы можете динамически генерировать URL, используемый в redirect. Например, если страница определяет переменную choice, Вы можете перенаправить клиента на страницу в зависимости от значения choice таким образом:
redirect ("http://www.royalairways.com/apps/page"
+ choice + ".html");
Если Вам нужно удостовериться, что текущие свойства client'а доступны в новом запросе и что Вы используете один из видов техники обслуживания объекта client на основе URL, Вы должны кодировать свойства в URL, передаваемом Вами в redirect. О том, как это сделать, см. .
В целом свойства объекта request и переменные верхнего уровня JavaScript существуют только в течение одиночного клиентского запроса. Если Вы выполняете перенаправление на новую страницу, Вам может понадобиться сохранить некоторую информацию для нескольких запросов. Вы можете сделать это, присоединив имена и значения свойств к URL, как описано в разделе .
Период Существования Объекта client
После того как клиент получил доступ к приложению, не гарантируется, будет он далее запрашивать продолжение обработки или продолжит выполнение до логического конца. В связи с этим объект client не имеет встроенного механизма окончания строка действия. Этот механизм позволяет JavaScript периодически "зачищать" старые объекты client, которые больше не нужны. Каждый раз, при получении сервером запроса на страницу приложения, JavaScript восстанавливает период существования объекта client.
Почтовая Служба/Mail Service
Вашему приложению может понадобиться отправить email-сообщение. Для этого Вы используете экземпляры класса SendMail. Единственным методом SendMail является send, для отправки сообщения, а errorCode и errorMessage служат для интерпретации ошибок.
Например, следующий скрипт отсылает почту в vpg со специфицированной темой/subject и телом сообщения:
SMName = new SendMail(); SMName.To = "vpg@royalairways.com";
SMName.From = "thisapp@netscape.com"; SMName.Subject = "Here's the information you wanted";
SMName.Body = "sharm, maldives, phuket, coral sea, taveuni, maui,
cocos island, marathon cay, san salvador"; SMName.send();
В таблице даны свойства класса SendMail. Свойства To и From необходимы; все остальные свойства - по выбору/optional.
To
Список разделённых запятыми первичных/primary получателей сообщения.
From
Имя пользователя/user name отправляющего сообщение.
Cc
Список разделённых запятыми дополнительных получателей сообщения.
Bcc
Список разделённых запятыми получателей сообщения, чьи имена не должны быть видны в сообщении.
Smtpserver
Имя почтового сервера (SMTP). По умолчанию это свойство имеет значение, установленное на сервере администрирования.
Subject
Тема сообщения.
Body
Текст сообщения.
Вы можете добавлять к этим свойствам любые другие. Все свойства класса SendMail включаются в шапку/header сообщения при фактической отправке. Например, следующий код отсылает сообщение получателю bill от vpg, устанавливая в поле vpg organization значение Royal Airways. Отвечает на сообщение от vpgboss.
mailObj["Reply-to"] = "vpgboss"; mailObj.Organization = "Royal Airways";
mailObj.From = "vpg"; mailObj.To = "bill"; mailObj.send();
Дополнительно о предопределённых полях шапки см. , стандарт формата текстовых сообщений Internet.
Класс SendMail позволяет отправлять простое текстовое почтовое сообщение или сложное MIME-сообщение. Вы можете также добавить в сообщению приложение/attachment. Для отправки MIME-сообщения добавьте свойство Content-type к объекту SendMail и укажите в нём MIME-тип сообщения.
Например, следующий участок кода отсылает изображение в формате GIF:
SMName = new SendMail(); SMName.To = "vpg@royalairways.com";
SMName.From = "thisapp@netscape.com"; SMName.Subject = "Here's the image file you wanted";
SMName["Content-type"] = "image/gif"; SMName["Content-Transfer-Encoding"] = "base64";
// В следующем операторе image2.gif обязан быть кодирован с базой 64/base 64.
// Если вы используете uuencode для кодирования GIF-файла, удалите header // (например, "begin 644 image2.gif") и замыкающий ("end"). fileObj = new File("/usr/somebody/image2.gif");
openFlag = fileObj.open("r"); if ( openFlag ) {
len = fileObj.getLength(); SMName.Body = fileObj.read(len);
SMName.send(); }
Некоторые MIME-типы требуют больше информации. Например, если content type это multipart/mixed, Вы обязаны также специфицировать сепаратор границ для одного или более различных наборов данных тела. Например, следующий код отсылает многочастное сообщение, содержащее две части, каждая из которых является обычным текстом:
SMName = new SendMail(); SMName.To = "vpg@royalairways.com";
SMName.From = "thisapp@netscape.com"; SMName.Subject = "Here's the information you wanted";
SMName["Content-type"] = "multipart/mixed; boundary=\"simple boundary\"";
fileObj = new File("/usr/vpg/multi.txt"); openFlag = fileObj.open("r"); if ( openFlag ) {
len = fileObj.getLength(); SMName.Body = fileObj.read(len);
SMName.send(); }
Вот файл multi.txt, содержащий многочастное сообщение:
Это место для преамбулы. Она игнорируется. Это удобное место для комментария, предназначенного для читателей, не знакомых с MIME. --простая граница Это первая часть тела сообщения. Это НЕ конец с символом обрыва строки.
--простая граница Content-Type: text/plain; charset=us-ascii
Это вторая часть тела сообщения. Это КОНЕЦ с символом обрыва строки.
--простая граница-- Это эпилог. Он также игнорируется.
Вы можете вкладывать друг в друга многочастные сообщения. То есть, если у Вас есть сообщение, content type которого многочастный, Вы можете включить другой многочастное сообщение в его тело. В таких случаях будьте внимательны и убедитесь, штаа каждый вложенный многочастный объект использует разные ограничители.
Детали о MIME-типах см. в
, MIME-стандарте. Об отправке почтовых сообщений в JavaScript см. также описание этого класса в книге
.
Поддерживаемые Клиенты БД и ODBC-Драйверы
В следующей таблице дано резюме по конкретным поставщикам БД, поддерживаемых на каждой платформе Netscape Enterprise Server 3.x (относительно Netscape Enterprise Server 4.0 см. замечания Enterprise Server 4.0 Release Notes). Данные поставщики БД не поддерживаются сервером Netscape FastTrack Server.
Поставщик БДAIX
DECIrix 6.2 >HP-UX 11.0
Solaris 2.5.1/2.6Windows NT 4.0 w/ SP4 DB2 CAE 2.1.2 Не поддерживается Не поддерживается V5.2
V5.2 V5.2
Informix Informix Client 7.22 Informix Client 7.22 Informix Client 7.22 SDK 2.10 (ESQL 9.16) SDK 2.10 (ESQL 9.16) SDK 2.10 TC1 (ESQL 9.16)
MicrosoftODBC ODBC Mgr Visigenic 2.0 Не поддерживается ODBC Mgr Visigenic 2.0 Не поддерживается
Поддерживается только на Solaris 2.5.1 MS SQL Server 6.5 (драйвер 3.60)
SQL Anywhere 5.5 (драйвер 5.00) MS Access 7.0 (драйвер 3.51.171300)
Oracle Oracle Client 7.3.x Oracle Client 7.3.x Oracle Client 7.3.x Oracle Client
8.0.5 Oracle Client
8.0.5 Oracle Client 8.0.5 Sybase Open
Client
/C 11.1 Open Client
/C 11.1 Open
Client /C 11.1 11.1.1 11.1.1 11.1.1
1Версия Oracle SQL*Net 1.1 больше не поддерживается.
В следующей таблице дано резюме по поддержке ODBC в Windows NT для Netscape Enterprise Server и Netscape FastTrack Server.
ODBC-КомпонентWindows NT 4.0 SP4 ODBC Manager MS ODBC Manager 3.51 MCAD 2.0 SP2
ODBC-Драйверы MS SQL Server 6.5
MS SQL Server Driver 3.60 (sqlsrv32.dll)
MS Access 7.0 MS Access Driver 3.51.171300 (odbcjt32.dll)
Sybase SQL Anywhere 5.5 Sybase SQL Anywhere Driver 5.00.0003 (wod50t.dll)
Обратите внимание, что ODBC не поддерживается на платформах Unix.
ПРИМЕЧАНИЕ:
Visigenic больше не обновляет свои существующие ODBC-драйверы или SDK. Вместо этого Visigenic избрал INTERSOLV для предоставления пути для обновления этих драйверов и продуктов. (См. ). Visigenic предоставит документ, покрывающий различия между драйверами Visigenic и INTERSOLV ODBC. В таблице перечислены возможности поддерживаемых ODBC-драйверов для NT.
SQL-БДСоединение
SQL passthrough/пропуск
Курсор "Только для чтения"
Обновляемый курсор
Хранимые процедуры
MS-SQL Server 6.5
Да
Да
Да
Да
Да
Sybase SQL Anywhere
Да
Да
Да
Да
Не проверено
Access
Да
Да
Да
Нет
N/A
Обратите внимание, что ODBC не поддерживается на платформах Unix.
и различные усовершенствования, которые обсуждаются
В JavaScript версии 1.4 появились новые возможности и различные усовершенствования, которые обсуждаются в онлайновом учебнике Core JavaScript Reference v1.4:
Также можно воспользоваться моим переводом на русский язык
.
В следующем списке резюмируются эти новые возможности:
Обработка исключений.
Вы можете вызывать/throw и отлавливать/catch исключения, используя операторы throw и try...catch.
Новые операторы in и instanceof.
Оператор in возвращает true, если специфицированное свойство имеется в специфицированном объекте. Оператор instanceof возвращает true, если специфицированный объект имеет специфицированный тип.
Изменения в LiveConnect.
Некоторые изменения в LiveConnect улучшили способ взаимодействия кодов Java и JavaScript:
Методы класса java.lang.Object наследуются в JavaArray. Дополнительно метод JavaArrary.toString теперь вызывает метод java.lang.Object.toString.
Вы можете передавать объект JavaClass в Java-метод, который требует аргумента типа java.lang.Class, вместо создания оболочки вокруг экземпляра класса java.lang.Class.
Вы не можете конструировать экземпляр JSException с детальным сообщением.Три первоначальных public-конструктора для Java-класса netscape.javascript.JSException, поддерживавшего эту возможность, не рекомендуются/deprecated. Вы не можете использовать операцию == для сравнения двух экземпляров JSObject. Используйте JSObject.equals.
Изменения в методе eval:
Метод верхнего уровня eval не может вызываться неявно. В предыдущих версиях лишь рекомендовалось, чтобы этот метод не вызывался неявно; начиная с JavaScript 1.4, неявный вызов eval может привести к ошибке времени выполнения. Это изменение повысит производительность.
Метод eval больше не доступен как метод класса Object; вместо него используйте функцию верхнего уровня eval.
Изменения в объекте Function:
Вы больше не должны специфицировать имя функции при использовании массива arguments; массив arguments это переменная, он больше не является свойством Function -объектов. Это изменение улучшит производительность.Не рекомендуется использовать свойство Function.arity. Оно заменено свойством Function.length.
Подключение Серверного JavaScript
Чтобы запускать приложения JavaScript на Вашем сервере, Вы обязаны подключить машину выполнения JavaScript в вашем Server Manager, щёлкнув Programs, а затем выбрав серверный JavaScript. После появления промпта "Activate the JavaScript application environment/Активизировать среду приложений JavaScript ?" выберите Yes и щёлкните OK. У Вас спросят также об ограничении доступа к Application Manager. Дополнительно см.
ПРИМЕЧАНИЕ:
Если Вы не подключите машину выполнения JavaScript, приложения JavaScript не смогут запускаться на этом сервере.
Чтобы использовать и сервлеты, и LiveWire, Вам необходимо подключить серверный JavaScript до подключения Java. Оба могут быть подключены через использование меню программ Administration Server'а. Если Вы модифицируете путь к классам/classpath в obj.conf, Ваши изменения будут утеряны, если Вы подключите/отключите серверный JavaScript или Java из программного меню Administration Server'а. Альтернативой редактирования директивы classpath в obj.conf является установка переменной окружения CLASSPATH в Unix или установка переменной CLASSPATH в установках System в Windows NT. Если Вам нужно редактировать obj.conf непосредственно, сохраните первоначальный файл на всякий случай. В Enterprise Server 4.0 Вы должны добавить CLASSPATH info в файлы конфигурации JVM (jvm12.conf для Solaris и NT) через интерфейс Enterprise Administration Server.
Как только Вы активируете среду приложений JavaScript, Вы обязаны остановить и рестартовать Ваш web-сервер, чтобы ассоциированные переменные окружения начали действовать. Если этого не сделать, приложения JavaScript, использующие службу LiveWire Database Service, работать не будут.
Получение Информации о Файле
Вы можете использовать несколько методов класса File для получения информации о файлах и работы с error-статусом.
Метод getLength возвращает число символов в текстовом файле или количество байтов в любом другом файле. Возвращает -1, если возникла ошибка.
fileObj.getLength();
Метод exists возвращает true, если файл существует, и false - в ином случае.
fileObj.exists();
Метод error возвращает статус ошибки или -1, если файл не открыт или не может быть открыт. Статус ошибки/error status это ненулевое значение, если ошибка возникла, и 0 в ином случае (нет ошибки). Коды статуса ошибки зависят от платформы; обратитесь к документации по Вашей ОС.
fileObj.error();
Метод clearError очищает error-статус (значение error) и значение eof.
fileObj.clearError();
Потоки
Java даёт вам возможность создавать раздельные потоки выполнения. Вы должны осторожно использовать эту возможность, если Ваш Java-код взаимодействует с JavaScript-кодом.
Каждый запрос серверного JavaScript обрабатывается в потоке, известном как request thread/поток запроса. Этот поток запроса ассоциируется с информацией о статусе, такой как контекст JavaScript, используемый для процессинга информации HTTP-запроса, и HTTP-буфер ответа.
Когда Вы вызываете Java-код из приложения JavaScript, этот код Java работает в том же самом потоке запроса, что и оригинальное приложение JavaScript. Java-код в этом потоке может взаимодействовать с приложением JavaScript и иметь гарантию, что оно является таким, как он ожидает. Точнее, он может полагаться на ассоциированную информацию статуса.
Однако Вы можете создать новый поток из Java-кода. Если Вы это сделаете, этот новый поток не сможет взаимодействовать с приложением JavaScript и не сможет опираться на информацию о статусе, ассоциированную с оригинальным потоком запроса. Если он попытается это сделать, поведение будет неопределённым. Например, создаваемый Вами Java-поток не может ни инициировать выполнение JavaScript-кода через использование JSObject, ни использовать writeHttpOutput, поскольку этот метод требует доступа к HTTP-буферу ответа.
Позиционирование Внутри Файла
Физический файл, ассоциированный с File -объектом, имеет указатель текущей позиции в файле. Когда Вы открываете файл, указатель находится в начале либо в конце файла, в зависимости от режима, использованного при открытии файла. В пустом файле начало и конец файла это одна точка.
Метод setPosition позиционирует указатель в файле, возвращая true при успехе и false - в ином случае.
fileObj.setPosition(position); fileObj.setPosition(position, reference);
Здесь fileObj это File -объект, position это целое число, указывающее позицию указателя, а reference указывает относительную точку для position таким образом:
0: относительно начала файла1: относительно текущей позиции 2: относительно конца файла
Иное (или unspecified): относительно начала файла
Метод getPosition возвращает текущую позицию в файле, где первый байт файла это всегда байт 0. Этот метод возвращает -1, если имеется ошибка.
fileObj.getPosition();
Метод eof возвращает true, если указатель находится в конце файла, и false - в ином случае. Этот метод возвращает true после первой операции чтения, которая пытается прочесть после конца файла.
fileObj.eof();
В этой книге рассматривается создание
В этой книге рассматривается создание приложений, написанных на языке "Серверный/Server-Side JavaScript" (SSJS). JavaScript это разработанный корпорацией Netscape платформонезависимый объектно-ориентированный язык скриптинга (сценариев) для клиентских и серверных приложений.
В данной главе имеются следующие разделы:
Предопределённые Объекты. Обзор.
Предопределённые объекты request, client, project и server содержат данные, существующие в течение различных периодов времени и доступные различным клиентам и приложениям. Имеется единственный объект server, используемый всеми запущенными на сервере приложениями. Имеется отдельный объект project для каждого запущенного приложения. Имеется один объект client для каждого браузера (клиент), выполняющего доступ к данному отдельному приложению. Наконец, имеется отдельный объект request для каждого клиентского запроса с определённого клиента к определённому приложению. На показаны возможности относительной доступности различных объектов.
Рисунок 6.1 Относительная доступность объектов, обслуживающих сессию
Машина выполнения JavaScript на сервере конструирует объекты обслуживания сессии в разные моменты времени. Эти объекты применяются для хранения различных данных. Вы можете определить специфические для приложения свойства для любого из этих объектов.
Объект request
Содержит данные, доступные только для текущего клиентского запроса. Ничто в этом объекте не применяется для совместного пользования. Объект request имеет предопределённые свойства, к которым Вы можете получить доступ.
Объект request считается объектом только для чтения. Машина выполнения сохраняет текущие значения всех элементов формы как свойства объекта request. Вы можете использовать его для хранения, информации, специфичной для отдельного запроса, но для этого более эффективным будет использование переменных JavaScript.
Машина выполнения конструирует объект request каждый раз, когда сервер отвечает на клиентский запрос из web-браузера. Он уничтожает этот объект в конце выполнения клиентского запроса. Машина выполнения не сохраняет данные объекта request.
См. дополнительно .
Объект client
Содержит данные, доступные только для отдельной пары клиент/приложение. Если один клиент соединён с двумя разными приложениями одновременно, машина выполнения JavaScript конструирует отдельные объекты client для каждой пары клиент/приложение. Все запросы от одного клиента к одному и тому же приложению пользуются одним и тем же объектом client. Объект client не имеет предопределённых свойств.
В общем, используйте объект client для тех данных, которые должны использоваться несколькими запросами от того же самого клиента (пользователя), но они не должны использоваться разными клиентами приложения. Например, Вы можете сохранять пользовательский ID потребителя как свойство объекта client.
Машина выполнения физически конструирует объект client для каждого клиентского запроса, но свойства сохраняются в течение времени существования клиентского соединения с приложением. Следовательно, хотя физически объект client существует только для одного клиентского запроса, концептуально Вы можете представлять, что он конструируется при первом соединении клиента с приложением и не разрушается, пока клиент не прервёт свой доступ к приложению. Есть несколько подходов к работе со свойствами объекта client при множественных запросах. См. дополнительно раздел .
Машина выполнения разрушает объект client, когда клиент заканчивает использование приложения. На практике машине JavaScript непросто определить, когда объект client и его свойства должны быть уничтожены. О том, как выполняется это определение, см. раздел . См. также .
Объект project
Содержит данные, доступные всем клиентам, выполняющим доступ к любой части приложения. Все клиенты, выполняющие доступ к одному и тому же приложению, используют один объект project. Объект project не имеет предопределённых свойств.
В общем, применяйте объект project для совместного использования данных несколькими клиентами, работающими с одним приложением. Например, Вы можете хранить следующий доступный ID потребителя как свойство объекта project. Когда объект project применяется для совместного использования данных, Вы должны быть внимательны относительно обеспечения одновременного доступа к этим данным; см. . Из-за ограничений, действующих для свойств объекта client, Вам иногда придётся использовать объект project для хранения данных отдельного клиента.
Машина выполнения конструирует объект project при старте приложения в Application Manager или при старте сервера. Она разрушает объект при остановке приложения или сервера.
Дополнительно см. .
Объект server
Содержит данные, доступные всем клиентам и всем приложениям данного сервера. Все приложения и все пары клиент/приложение используют один объект server. Объект server имеет предопределённые свойства.
Применяйте объект server для совместного использования данных несколькими приложениями сервера. Например, Вы можете использовать объект server для отслеживания использования всех приложений сервера. Когда объект server применяется для совместного использования данных, Вы должны побеспокоиться об обеспечении одновременного доступа к этим данным; см. .
Машина выполнения конструирует объект server при старте сервера и разрушает его при остановке сервера.
См. дополнительно .
может помочь представить, как все эти объекты соответствуют URL страницы Вашего приложения.
Рисунок 6.2 Предопределённые объекты в URL
На этом рисунке Joe запрашивает URL http://www.royalairways.com/videoapp/category.html, соответствующий странице приложения videoapp. Когда машина выполнения получает запрос, она использует уже существующий объект server, соответствующий www.royalairways.com и уже существующий объект project, соответствующий приложению videoapp. Машина создаёт объект client, соответствующий комбинации Joe и приложения videoapp. Если Joe уже получал доступ к другим страницам этого приложения, новый объект client использует любые сохранённые свойства. Наконец, машина создаёт новый объект request для конкретного запроса на страницу category.html.
Образец Flexi
Приложение flexi иллюстрирует использование серверного JavaScript для доступа к удалённому сервису, запущенному на ORB с включённым протоколом IIOP, а также показывает удалённый сервис, написанный целиком на Java с использованием ISB for Java. И исходные файлы, и исполняемые файлы приложения flexi установлены в директории $NSHOME\js\samples\flexi.
A flexible spending account (FSA)/гибко расходуемый счёт это счёт, на котором служащие могут хранить доллары предоплаты, используемые для медицинских расходов. Служащие обычно подписываются на этот план через администратора плана и выбирают сумму в долларах, которую они хотят хранить на своих счетах. Если служащий осуществляет затраты на медицинские цели, он отправляет запрос, который, если одобрен, вызывает снятие суммы со счёта и перевод её служащему.
Приложение flexi предоставляет поддержку обслуживания FSA. В этом приложении администратор имеет следующие опции:
Создание нового счёта с указанным балансом.
Выбор существующего счёта по фамилии служащего.
Хранение дополнительных вложений на выбранном счёте.
Закрытие счёта.Принятие или отказ в выполнении запроса, отправленного служащим.
Для служащего имеются следующие опции:
Просмотр статуса счёта, включая статус любого отклонённого запроса.
Отправка нового запроса путём заполнения формы.
JavaScript-Вызова Java
Директория $NSHOME\js\samples\bugbase содержит простое приложение, иллюстрирующее использование LiveConnect. В этом разделе описан код JavaScript этого приложения-образца. См. в разделе описание кода Java этого приложения.
Приложение bugbase представляет собой простую БД "жучков". Вы вводите bug, заполняя клиентскую форму номером жучка, приоритетом, продуктом, в котором он обнаружен, и кратким описанием. Другая форма позволяет просмотреть существующий bug.
Следующий JavaScript обрабатывает акцию входа:
// . проверить, что ID был введён.
if (request.bugId != "") { // . Создаётся Bug-экземпляр и присваивается переменной. var bug = new Packages.bugbase.Bug(parseInt(request.bugId),
request.bugPriority, request);
// . Получить доступ к массиву и сохранить экземпляр в нём.
project.bugsLock.lock(); project.bugs[parseInt(request.bugId)] = bug; project.bugsLock.unlock();
// . Отобразить информацию.
write("====>Committed bug: ");
write(bug, " "); } // . Если ID не был введён, предупредить пользователя. else { write("====>Couldn't commit bug: please complete all fields. "); }
Шаги в этом коде:
Проверить, что пользователь ввёл ID для bug. Только в этом случае выполняется вход в bug.
Создать экземпляр Java-класса Bug и присвоить его переменной bug. Конструктор класса Bug принимает три параметра: два из них являются свойствами объекта request; третий это сам объект JavaScript request. Поскольку они являются элементами формы, эти свойства объекта request являются строками JavaScript. Код изменяет ID на целое число перед передачей его Java-конструктору. После передачи request -объекта Java-конструктору этот конструктор может затем вызывать его методы. Этот процесс обсуждается в разделе .Использовать project.bugsLock для получения исключительного доступа к массиву project.bugs и сохранить затем новый Bug -экземпляр в этом массиве, индексированным по номеру bug'а, специфицированному в форме. Заметьте, что этот код сохраняет ссылку на Java-объект как значение свойства JavaScript-объекта. О блокировке см. .
Отобразить клиенту информацию о bug'е, который Вы только что сохранили.Если bug ID не введён, вывести сообщение о том, что bug не может быть найден в БД.
Пример Вызывающего Серверного JavaScript
В директории $NSHOME\js\samples\bugbase содержится простое приложение, которое иллюстрирует использование LiveConnect. В это разделе описывается приложение-образец Java-кода. См. в разделе описание основ работы этого приложения и его JavaScript-кода.
// . Импортировать необходимые Java-объекты. package Bugbase; import netscape.javascript.*; import netscape.server.serverenv.*;
// . Создать класс Bug. public class Bug {
int id; String priority; String product;
String description; String submitter;
// . Определить конструктор класса.
public Bug(int id, String priority, JSObject req)
throws java.io.IOException {
// Записать часть http-ответа.
NetscapeServerEnv.writeHttpOutput("Java constructor: Creating
a new bug. ");
this.id = id;
this.priority = priority;
this.product = (String)req.getMember("bugProduct");
this.description = (String)req.getMember("bugDesc");
} // . Возвратить строковое представление объекта. public String toString()
{ StringBuffer result = new StringBuffer();
result.append("\r\nId = " + this.id
+ "; \r\nPriority = " + this.priority
+ "; \r\nProduct = " + this.product
+ "; \r\nDescription = " + this.description);
return result.toString();
} }
Многие шаги в этом коде не являются специфичными для взаимодействия с JavaScript. Только шаги 1 и 3 имеют отношение к JavaScript.
Специфицировать пакет, используемый в файле, и импортировать пакеты netscape.javascript и netscape.server.serverenv. Если Вы пропустите этот шаг, Вы не сможете использовать объекты JavaScript.
Создать Java-класс Bug, специфицировать его поля.
Определить конструктор для этого класса. Этот конструктор принимает три параметра: целое число, строку и объект типа JSObject. Этот последний параметр является представлением JavaScript-объекта в Java. Через методы этого объекта конструктор может получить доступ к свойствам и вызвать методы объекта JavaScript. В этом случае он использует метод getMember объекта JSObject для получения значений свойств JavaScript-объекта. Также этот метод использует метод writeHttpOutput предопределённого объекта NetscapeServerEnv (из пакета netscape.server.serverenv) для вывода информации в процессе конструирования объекта. Этот метод записывает массив байтов в тот же поток вывода, который используется JavaScript-функцией write.
Определить метод toString. Это стандартный метод для Java-объекта, возвращающий строковое представление полей объекта.
образец Viewer. Поскольку это приложение
На сервере Netscape имеется приложение- образец Viewer. Поскольку это приложение даёт возможность просматривать файлы на сервере, оно не устанавливается автоматически.
Viewer это хороший пример использования класса File. Если Вы установили это приложение, позаботьтесь об ограничении доступа к нему, чтобы неавторизованный пользователь не мог просматривать файлы на сервере. Об ограничении доступа к приложению см. раздел .
Следующий код из приложения Viewer создаёт экземпляр класса File, открывает его для чтения и генерирует HTML, отражающий строки файла, с разделительной линией после каждой строки.
x = new File("\tmp\names.txt"); fileIsOpen = x.open("r");
if (fileIsOpen) { write("file name: " + x + " ");
while (!x.eof()) { line = x.readln();
if (!x.eof())
write(line+" "); }
if (x.error() != 0) write("error reading file" + " "); x.close(); }
Primitive value/примитивное значение
Данные, непосредственно представленные на самом нижнем уровне языка. Примитивное значение JavaScript является членом одного из следующих типов: undefined, null, Boolean, number или string.
Вот примеры некоторых примитивных значений:
a=true // Boolean/Булево b=42 // number/число
c="Hello world" // string/строка if (x==undefined) {} // undefined ("не определено") if (x==null) {} // null
Присоединение Свойств Объекта client к URL Вручную
При использовании кодирования URL на клиенте или на сервере для работы с объектом client машина выполнения обычно должна сохранять соответствующую информацию (имена и значения свойств объекта client или индекс серверной структуры данных) во всех URL, высылаемых клиенту, вне зависимости от того, являются ли эти URL как статический HTML или были сгенерированы операторами серверного JavaScript.
Машина выполнения автоматически присоединяет соответствующую информацию к гиперссылкам HTML, находящимся вне тэгов SERVER. Так, например, предположим, что Ваша HTML-страница содержит следующие операторы:
For more information, contact
Royal Airways ...
Если приложение использует кодирование URL для объекта client, машина выполнения автоматически присоединит client -информацию в конец URL. Вы не должны ничего делать специально для поддержки этого поведения.
Однако ваше приложение может использовать функцию write для динамической генерации оператора HTML, содержащего URL. Вы можете также использовать функцию redirect для старта нового запроса. Когда Вы используете операторы серверного JavaScript для добавления URL к генерируемой HTML-странице, машина выполнения предполагает, что Вы специфицировали полный URL для отправки в нужном Вам виде. Она не присоединяет автоматически клиентскую информацию даже при использовании кодирования URL для работы с объектом client. Если Вам нужно присоединить клиентскую информацию, Вы обязаны сделать это сами.
Вы используете функцию addClient для добавления вручную соответствующей client -информации. Эта функция принимает URL и возвращает новый URL с присоединённой информацией. Например, предположим, что контактный URL варьируется в зависимости от значения свойства client.contact. Вместо вышеприведённого HTML Вы можете ввести следующее:
For more information, contact
if (client.contact == "VIP") { write ("");
write ("Royal Airways VIP Contact "); } else {
write ("");
write ("Royal Airways "); } ...
Теперь машина выполнения не присоединяет свойства объекта client к URL. Если Вы используете один из видов техники кодирования URL для работы с объектом client, может возникнуть проблема. Тогда, если Вы хотите отправить свойства объекта client с этим URL, используйте такой код:
For more information, contact
if (client.contact == "VIP") { write (addClient(
""));
write ("Royal Airways VIP Contact "); } else {
write (addClient( ""));
write ("Royal Airways "); } ...
Также всякий раз, когда Вы применяете функцию redirect для перенаправления клиентского запроса, Вы должны использовать addClient для присоединения информации, как здесь:
redirect(addClient("mypage.html"));
В противоположность этому, если Ваша страница имеет ссылку на URL вне Вашего приложения, Вам может не понадобиться присоединение клиентской информации. Тогда не используйте статическую строку в значении атрибута HREF. Вместо этого вычисляйте значение. Это предотвратит автоматическое присоединение машиной выполнения клиентского индекса или свойств к URL. Например, у вас имеется ссылка:
В этом случае машина выполнения присоединяет клиентскую информацию. Чтобы этого не было, используйте очень похожую ссылку:
Хотя приложение первоначально инсталировано для использования техники без кодирования URL для работы с client, оно может быть позднее модифицировано для использования техники кодирования URL. Следовательно, если Ваше приложение генерирует динамические URL или использует redirect, Вам всегда нужно будет использовать addClient.
Прямая Замена
Вы можете также использовать серверный JavaScript для генерирования клиентских скриптов. Эти значения могут использоваться в последовательности операторов на клиенте. В качестве простого примера Вы можете инициализировать клиентскую переменную по имени budget на основе значения client.amount таким образом:
The budget is:
Если значение client.amount равно 50, это сгенерирует такой JavaScript:
The budget is:
При запуске на клиенте это будет выглядеть так:
The budget is: 50
Проблемы Безопасности
Соблюдайте осторожность при использовании класса File. Приложение JavaScript может читать или записывать файлы везде, где позволяет операционная система, в том числе, возможно, и в системных файлах. Вы должны быть уверены, что Ваше приложение не позволяет читать файлы паролей и другую закрытую информацию или записывать в файлы. Делайте так, чтобы имена файлов, которые Вы передаёте в методы, не могли быть изменены хакерами.
Например, не используйте свойства объектов client или request в качестве имён файлов, поскольку эти значения могут стать доступными хакеру через куки или URL. В таких случаях хакер сможет модифицировать куки или URL, чтобы получить доступ к закрытым файлам.
Исходя из таких же соображений, Navigator не предоставляет автоматического доступа к файловой системе клиентской машины. Если необходимо, пользователь может сохранять информацию непосредственно в клиентской файловой системе, делая соответствующий выбор в меню Navigator'а.
Процессинг Времени Прогона на Сервере
В разделе показано, что происходит на этапе прогона, если пользователь выполняет доступ к странице приложения JavaScript. В данном разделе детально рассматриваются этапы этого процесса со 2 по 4, чтобы Вы смогли лучше понять, что происходит на каждом этапе. Это описание предоставляет контекст для понимания того, что Вам нужно делать на клиенте и сервере.
При работе с приложениями JavaScript важно помнить об асинхронной природе процессов Web. Приложения JavaScript разрабатываются для использования многими пользователями одновременно. Машина выполнения JavaScript на сервере обрабатывает запросы нескольких пользователей по мере их поступления и выполняет их в порядке поступления.
В отличие от традиционного приложения, которое запускается отдельным пользователем на отдельной машине, Ваше приложение обязано поддерживать одновременный доступ нескольких пользователей. Фактически, поскольку каждый фрэйм (кадр) HTML-документа из нескольких фрэймов генерирует свой собственный запрос/request, для машины выполнения может оказаться, что запрос одного пользователя является множественным запросом.
HTTP (Hypertext Transfer Protocol) это протокол, по которому HTML-страница пересылается клиенту. Этот протокол является stateless\бесстатусным, то есть информация не сохраняется в период между запросами. В общем, любая информация, необходимая для обработки HTTP-запроса, должна пересылаться вместе с этим запросом. Это создаёт проблемы для многих приложений. Как использовать информацию одновременно различными пользователями приложения или даже различными запросами одного пользователя? Служба JavaScript Session Management Service была разработана для того, чтобы помочь разрешить эту проблему. Детально эта служба рассматривается в В данный момент просто помните, что машина выполнения автоматически обслуживает объекты client, server, project и request.
Если Netscape-сервер получает клиентский запрос на страницу приложения, он сначала выполняет авторизацию (идентификацию). Этот шаг является частью базовых функций администрирования сервера. Если попытка авторизации запроса не удалась, последующие шаги не выполняются. Если запрос получил авторизацию сервера, машина выполнения JavaScript продолжает работу. Она выполняет следующие шаги, описанные в последующих разделах:
Конструирует новый объект request и конструирует или восстанавливает объект client.
Находит страницу для запроса и начинает создание HTML-страницы для отправки клиенту.
Для каждого участка исходной HTML-страницы: добавляет его в буфер или исполняет код.Сохраняет свойства объекта client.
Высылает HTML клиенту.Уничтожает объект request и сохраняет или уничтожает объект client.
Прототипы
Как указано в книге , Вы можете использовать свойство prototype многих классов, чтобы добавлять новые свойства в класс и во все его экземпляры. Как описано в разделе , серверный JavaScript добавляет несколько классов и предопределённых объектов. В новых классах, имеющих свойство prototype, оно работает в серверном JavaScript точно так же, как и в клиентском JavaScript.
Вы можете использовать свойство prototype для добавления новых свойств в классы Blob, Connection, Cursor, DbPool, File, Lock, Resultset, SendMail и Stproc. Кроме того, Вы можете использовать свойство prototype класса DbBuiltin для добавления свойств в предопределённый объект database. Обратите внимание, что Вы не можете создать экземпляр класса DbBuiltin; вместо этого Вы используете объект database, предоставляемый машиной выполнения JavaScript.
Вы не можете использовать prototype с объектами client, project, request и server.
Так же, как и в клиентском JavaScript, Вы можете использовать свойство prototype для любого класса, который Вы определяете в своём приложении.
Помните, что все приложения JavaScript на сервере работают в одной среде. Вот почему Вы можете распределять информацию между клиентами и приложениями. Следствием этого, однако, является то, что при использовании свойства prototype для добавления нового свойства в любой серверный класс, добавленный языком JavaScript, новое свойство доступно всем приложениям, работающим на сервере, а не только приложению, в котором это свойство было добавлено. Это даёт возможность легко добавлять функциональность всем приложениям JavaScript на Вашем сервере.
В противоположность этому, если Вы добавляете свойство в класс, который Вы определили в своём приложении, это свойство доступно только в том приложении, где оно было создано.
Проверка Конфигурации Вашей БД
После выполнения установки, описанной в данной главе, Вы можете использовать приложение-образец dbadmin для проверки правильности работы Вашего соединения с БД. Вы используете это приложение JavaScript для соединения с Вашим сервером БД и выполнения различных несложных задач, таких как выполнение оператора SELECT и отображение результатов или отправки произвольных SQL-команд серверу.
Поскольку dbadmin может использоваться для модификации и удаления таблиц БД, доступ к ней автоматически ограничен, если Вы выбрали защищённый режим Application Manager. Дополнительно об ограничении Application Manager см. .
Первое, что Вы обязаны сделать при использовании dbadmin, это соединиться с БД. Выберите Connect to Database. Появится форма, показанная на , где вы можете ввести информацию о соединении. Введите параметры и щёлкните Connect, чтобы попытаться установить соединение с сервером. О параметрах соединения см. , а также описание метода connect в книге Серверный JavaScript. Справочник.
Если соединение установилось, появляется страница Execute Query. Это означает, что ваша БД соответствующим образом сконфигурирована для работы с LiveWire Database Service. Если соединиться не удалось, появится страница Database Connect Error. В этом случае убедитесь, что Вы следовали инструкциям по конфигурированию конкретной БД и "железа".
Проверка Ошибочных Условий
При написании приложения на языке JavaScript Вы должны знать о различных ошибках. В тех случаях, когда Вы используете LiveWire Database Service для взаимодействия с реляционной БД, ошибки могут возникать по разным причинам. Например, SQL-операторы могут не выполняться из-за ограничений ссылочной целостности/referential integrity, потери привилегий доступа, блокировки записи или таблицы в многопользовательской БД и т.д. Если акция терпит неудачу, сервер БД возвращает сообщение об ошибке с указанием причины.
Ваш код должен проверять наличие ошибок и обрабатывать их соответствующим образом.
Публикация Приложения
После завершения разработки и тестирования приложения Вы можете опубликовать его и сделать доступным для предполагаемых пользователей. Это требует выполнения двух шагов:
перемещения/копирования приложения с рабочего сервера на сервер публикаций, доступный конечным пользователям;
применения или изменения прав доступа к приложению.
Вы должны скопировать web-файл приложения на сервер публикаций вместе с изображениям и неоткомпилированными файлами HTML и JavaScript, которые необходимы для работы приложения. О публикации файлов приложений см. дополнительно Netshare and Web Publisher User's Guide.
ПРИМЕЧАНИЕ:
В целом, по соображениям безопасности, Вы не должны публиковать файлы с исходным кодом.
В зависимости от приложения, Вы можете ограничить доступ для определённых пользователей или групп пользователей. В некоторых случаях любой пользователь может запускать приложение; тогда ограничений можно вообще не применять. Если приложение показывает специальную информацию или даёт доступ к файловой системе сервера, Вы должны предоставить доступ только авторизованным пользователям, имеющим соответствующие имена и пароли для входа.
Вы ограничиваете доступ к приложению, применяя стиль конфигурации сервера из Вашего Server Manager. Об использовании Server Manager и стилей конфигурации см. Enterprise Server 4.0 Administrator's Guide.
Пулы Соединений с БД
Если Вы хотите использовать объект database, Вам не нужно создавать его. Это предопределённый объект, предоставляемый машиной выполнения JavaScript. Если Вам нужны дополнительные возможности класса DbPool, Вы создаёте экземпляр класса DbPool и соединяете этот объект с конкретной БД, которая создаёт пул соединений.
Вы можете создать общий DbPool-объект и специфицировать позднее информацию соединения (используя метод connect), или можете специфицировать информацию соединения при создании пула. Общий DbPool-объект не имеет никаких доступных соединений в момент его создания. Исходя из этого, Вам может понадобиться установить соединение при создании этого объекта. Если Вы используете объект database, Вы всегда обязаны устанавливать соединение путём вызова метода database.connect.
connect (dbtype, serverName, userName, password, databaseName, maxConnections, commitFlag);
При создании соединения Вы можете специфицировать следующую информацию, либо при создании DbPool-объекта, либо при вызове метода connect объекта DbPool или database:
dbtype: Тип БД. Обязан быть "DB2", "INFORMIX", "ODBC", "ORACLE" или "SYBASE". (Для приложений, запущенных на сервере Netscape FastTrack Server, обязан быть "ODBC".)
serverName: Имя сервера БД, с которым устанавливается соединение. Имя сервера обычно назначается при установке БД. В случае сомнений, узнайте у администратора БД или системы.
username: Имя пользователя, соединяющегося с БД.password: Пароль пользователя.
databaseName: Имя БД на данном сервере, с которой устанавливается соединение. Если Ваш сервер баз данных поддерживает множество БД на одном сервере, предоставьте имя используемой БД. Если предоставлена пустая строка, производится соединение с БД по умолчанию. Для Oracle, ODBC и DB2 Вы всегда обязаны предоставлять пустую строку.
maxConnections: (Optional/Необязательный Параметр) Допустимое количество соединений в пуле БД. Помните, что клиентская лицензия Вашей БД, возможно, специфицирует максимальное количество соединений. Не устанавливайте этот параметр в число, превышающее количество, допустимое по лицензии. Если Вы не предоставляете этот параметр для объекта DbPool, он имеет значение 1. Если Вы не предоставляете этот параметр для объекта database, его значением будет то, что Вы специфицировали в Application Manager как значение для Built-in Maximum Database Connections/Встроенное Значение Максимального Количества Соединений с БД, когда устанавливали приложение. (См. ). См. в разделе о том, что Вы должны предусмотреть при установке этого параметра.
commitflag: ( Необязательный Параметр) Булево значение, указывающее, подтвердить ли открытую транзакцию или выполнить её откат при закрытии соединения. Специфицируйте true для подтверждения открытой транзакции и false - для выполнения отката. Если этот параметр Вами не предоставлен для объекта DbPool, его значением будет false. Если этот параметр не предоставлен для объекта database, значением параметра будет true.
Например, следующий оператор создаёт новый пул БД из 5 соединений с БД Oracle. В этом пуле неподтверждённые транзакции откатываются:
pool = new DbPool ("ORACLE", "myserver1", "ENG", "pwd1", "", 5);
Приложение-образец dbadmin позволяет Вам экспериментировать с соединениями с различными БД как разным пользователям.
Для многих приложений Вы, возможно, захотите выполнять совместное использование набора соединений несколькими клиентами, или чтобы соединение захватывало несколько клиентских запросов. В этих случаях Вы должны устанавливать соединение на начальной странице Вашего приложения. Это позволит исключить возможные проблемы в тех случаях, когда отдельные клиенты выполняют совместные соединения с БД.
Однако для некоторых приложений каждый клиент должен выполнять своё собственное соединение. Как сказано в разделе клиенты могут совместно использовать объекты. Если это так, убедитесь, что блокировки используются для управления совместным использованием данных, как указано в разделе .
В следующей таблице показаны методы объектов DbPool и database для обслуживания пула соединений. (Объект database использует другие методы, рассмотренные ранее, для работы с соединением с БД.)
connect
Соединяет пул с определённой конфигурацией БД и пользователя.
connected
Проверяет, соединён ли пул и все его соединения с базой данных.
connection
(Только DbPool) Запрашивает доступный Connection-объект из пула.
disconnect
Отсоединяет все соединения пула от БД.
majorErrorCode
Главный код ошибки, возвращаемый сервером БД или ODBC.
majorErrorMessage
Главное сообщение об ошибке, возвращаемое сервером БД или ODBC.
minorErrorCode
Вторичный код ошибки, возвращаемый библиотекой продавца.
minorErrorMessage
Вторичное сообщение об ошибке, возвращаемое библиотекой продавца.
Работа с Датами и Базами Данных
Значения даты, запрошенные из базы данных, конвертируются в Date -объекты JavaScript. Чтобы вставить значение даты в БД, используйте Date -объект JavaScript так:
cursorName.dateColumn = dateObj
Здесь cursorName это курсор, dateColumn это столбец, соответствующий дате, а dateObj это Date -объект JavaScript. Вы создаёте Date -объект, используя оператор new и Date -конструктор:
dateObj = new Date(dateString)
где dateString это строка, представляющая дату. Если dateString - пустая строка, создаётся Date -объект для текущей даты. Например:
custs.orderDate = new Date("Jan 27, 1997")
Примечание:
Базы Данных DB2 имеют типы данных time и timestamp. Эти типы конвертируются в тип Date в JavaScript.
ПРЕДУПРЕЖДЕНИЕ! LiveWire Database Service не может обрабатывать даты после 5 февраля 2037 года. Дополнительно о работе с датами в JavaScript см.
Работа с Двоичными/Бинарными Данными
Двоичные данные для мультимедиа-содержимого, такого как изображение или звуковой файл, хранятся в БД в виде большого двоичного объекта/binary large object (BLOb). Можно использовать технику двух видов для обработки бинарных данных в приложениях JavaScript:
Хранить имена файлов в БД, а данные - в отдельных файлах.
Хранить данные в БД как BLOb'ы и осуществлять доступ к ним через методы класса Blob.
Если Вам не нужно хранить BLOb-данные в БД, Вы можете хранить в БД имена файлов и осуществлять доступ к этим файлам в Вашем приложении с помощью стандартных тэгов HTML. Например, если Вы хотите вывести изображение в каждом ряду таблицы БД, Вы можете создать в таблице столбец с названием imageFileName, содержащий имя нужного файла изображения. Затем можно использовать такое выражение HTML для показа изображения в каждом ряду:
Когда курсор проходит по таблице, имя файла в тэге IMG изменяется на ссылку на соответствующий файл.
Для того чтобы Вы могли манипулировать реальными двоичными данными в Вашей БД, машина выполнения JavaScript распознаёт значения столбца, являющиеся BLOb-данными. То есть, когда программа создаёт объект Cursor, если один из столбцов таблицы БД содержит BLOb-данные, программа создаёт Blob -объект для соответствующего значения в объекте Cursor. Вы можете затем использовать методы Blob -объектов для отображения этих данных. Также, если нужно вставить BLOb-данные в БД, программа предоставляет Вам для использования глобальную функцию.
В таблице показаны методы и функции для работы с BLOb-данными.
Метод или ФункцияОписание
blobImage
Метод, используемый при отображении BLOb-данных, хранимых в БД. Возвращает тэг HTML IMG для специфицированного типа изображения (GIF, JPEG и т.д.).
blobLink
Метод, используемый при создании ссылки, которая указывает на BLOb-данные гиперссылкой. Возвращает гиперссылку HTML на BLOb.
blob
Глобальная функция, используема для вставки или обновления данных в ряду, содержащем BLOb-данные. Присваивает BLOb-данные столбцу в курсоре.
Метод blobImage вызывает BLOb из БД, создаёт временный файл специфицированного формата и генерирует HTML-тэг IMG, который ссылается на временный файл. Машина выполнения удаляет временный файл после генерации страницы и отправки её клиенту.
Метод blobLink вызывает BLOb-данные из БД, создаёт временный файл и генерирует гипертекстовую ссылку HTML на этот временный файл. Машина выполнения удаляет временный файл после того как пользователь щёлкнет на ссылке или через 60 секунд после того как запрос будет выполнен.
Следующий пример иллюстрирует использование blobImage и blobLink для создания временных файлов. В данном случае таблица FISHTBL содержит 4 столбца: ID(ентификатор), name/имя и два изображения. Одно из них является уменьшенной копией/thumbnail изображения; другое - большим изображением. Код записывает HTML для отображения имени, уменьшенной копии и ссылки на большое изображение.
cursor = connobj.cursor ("select * from fishtbl");if ( cursor && (connobj.majorErrorCode() == 0) ) {
while (cursor.next()) { write (cursor.name);
write (cursor.picture.blobImage("gif"));
write (cursor.picture.blobLink("image\gif", "Link" + cursor.id));
write (" "); }
cursor.close(); }
Если FISHTBL содержит ряды для 4 рыб, пример может дать на выходе такой HTML:
Cod
Link1 Anthia
Link2 Scorpion Link3 Surgeon
Link4
Если Вам нужно добавить BLOb-данные в БД, используйте глобальную функцию blob. Она вводит BLOb-данные в столбец в обновляемом курсоре. В противоположность blobImage и blobLink, функция blob является функцией верхнего уровня, а не методом.
Следующие операторы вставляют BLOb-данные в столбцы ряда, а затем обновляют этот ряд таблицы FISHTBL в БД. В курсоре имеется единственный ряд.
// Начало транзакции. database.beginTransaction();
// Создание курсора. fishCursor = database.cursor ("select * from fishtbl where name='Harlequin Ghost Pipefish'", true);
// Убедимся, что курсор создан. if ( fishCursor && (database.majorErrorCode() == 0) ) {
// Позиционируем указатель на ряд.
rowexists = fishCursor.next();
if ( rowexists ) { // Присваиваем/вставляем blob-данные.
fishCursor.picture = blob ("c:\\data\\fish\\photo\\pipe.gif"); // Обновляем ряд. fishCursor.updateRow ("fishtbl"); // Закрываем курсор и подтверждаем изменения. fishCursor.close();
database.commitTransaction(); }
else {
// Иначе закрываем курсор и выполняем откат транзакции. fishCursor.close();
database.rollbackTransaction(); } }
else {
// Иначе вообще не получаем курсор; откатываем транзакцию.
database.rollbackTransaction(); }
Помните, что backslash (\) это escape-символ в JavaScript. Исходя из этого, Вы обязаны использовать двойной обратный слэш в именах файлов NT, как было в данном примере.
Работа с Файлами
Класс File имеет несколько методов, которые можно использовать после открытия файла:
Позиционирование: setPosition, getPosition, eof. Это методы для установки и получения текущей позиции указателя в файле и для определения, не находится ли указатель в конце файла.
Чтение из файла: read, readln, readByte.
Запись в файл: write, writeln, writeByte, flush.
Конвертация двоичного и текстового форматов: byteToString, stringToByte. Конвертируют одно число в символ и наоборот.
Информационные методы: getLength, exists, error, clearError. Для получения информации о файле и для получения и очистки error-статуса.
Эти методы описаны в последующих разделах.
Работа с Картами Изображений/Image Maps
Атрибут ISMAP тэга IMG указывает на серверную карту изображений. Если пользователь щёлкает на карте, горизонтальная и вертикальная позиции курсора высылаются на сервер. Свойства imageX и imageY возвращают эти координаты. Рассмотрим такой HTML:
ISMAP ALT="SANTA CRUZ COUNTY">
Страница mapchoice.html получает свойства request.imageX и request.imageY на основе позиции курсора в момент щелчка мышью.
Работа с Массивами Java
Если какой-нибудь метод Java создаёт массив и Вы обращаетесь к этому массиву в JavaScript, Вы работаете с JavaArray. Например, следующий код создаёт JavaArray x из 10 элементов типа int:
theInt = java.lang.Class.forName("java.lang.Integer")
x = java.lang.reflect.Array.newInstance(theInt, 10)
Подобно объекту JavaScript Array, JavaArray имеет свойство length, возвращающее количество элементов массива. В отличие от Array.length, JavaArray.length является свойством только для чтения/read-only, поскольку количество элементов в Java-массиве фиксируется в момент создания.
Работа с Оболочками
В JavaScript wrapper\оболочка это объект типа данных целевого языка, который содержит в себе объект исходного языка. На стороне JavaScript Вы можете использовать объект-оболочку для доступа к методам и полям Java-объекта; вызывая метод или получая доступ к свойству в оболочке даёт в результате вызов Java-объекта. На стороне Java объекты JavaScript оборачиваются в экземпляры класса netscape.javascript.JSObject и передаются в Java.
Когда JavaScript-объект высылается в Java, машина выполнения создаёт Java-оболочку типа JSObject; когда JSObject высылается из Java в JavaScript, машина выполнения разворачивает его в объект оригинального типа JavaScript. Класс JSObject предоставляет интерфейс для вызова методов JavaScript и проверки свойств JavaScript.
Работа с Параметрами Вывода
Этот этап касается хранимых процедур Sybase, Oracle, DB2 или ODBC. Для процедур Informix методы, обсуждаемые здесь, не применяются.
Чтобы определить количество параметров вывода процедуры (включая параметры и вывода, и ввода/вывода), Вы используете метод outParamCount. Вы можете работать с параметрами вывода хранимой процедуры, используя метод outParameters объекта. Если outParamCount возвращает 0, хранимая процедура не имеет параметров вывода. В этой ситуации не вызывайте outParameters.
Например, предположим, Вы создали хранимую процедуру, которая находит фамилию служащего по заданному ID. Если имеется фамилия служащего, ассоциированная с данным ID, процедура возвращает 1, и её output-параметр содержит фамилию служащего. Иначе параметр вывода является пустым. Следующий код выводит фамилию служащего или сообщение о том, что фамилия не найдена:
id = 100; getNameProc = connobj.storedProc("getName", id);
returnValue = getNameProc.returnValue(); if (returnValue == 1) write ("Name of employee is " + getNameProc.outParameters(0)); else
write ("No employee with id = " + id);
Предположим, хранимая процедура имеет один параметр ввода, один параметр ввода/вывода и один параметр вывода. Далее примем, что вызов хранимой процедуры отсылает значение параметра ввода и параметра ввода/вывода, как показано здесь:
spobj = connobj.storedProc("myinout", 34, 56);
Метод outParameters возвращает любые параметры ввода/вывода до того как возвратит первый параметр вывода.
В предыдущем примере, если Вызывается outParameters(1), возвращается значение, возвращаемое хранимой процедурой. И наоборот, если вызывается outParameters(0), метод возвращает 56. Это значение, переданное хранимой процедуре в позиции параметра ввода/вывода.
ПРИМЕЧАНИЕ:
Параметры вывода не могут быть null; однако Вы можете присвоить null-значение параметра ввода или ввода/вывода. В DB2, ODBC и Sybase Вы обязаны запрашивать resultSet -объекты и использовать метод returnValue до того, как вызываете outParameters. После того как Вы вызвали returnValue или outParameters, Вы больше не сможете получить данные из результирующего набора и не сможете получить какие-либо дополнительные результирующие наборы. Вы должны вызывать outParameters после обработки результирующего набора и любых return-значений.
Работа с Return-Значениями
Этот этап относится к хранимым процедурам Sybase и Oracle. Для процедур Informix, ODBC и DB2 метод returnValue всегда возвращает null.
Если Ваша хранимая процедура возвращает значение (return value), Вы можете получить к нему доступ с помощью метода returnValue.
В DB2, ODBC и Sybase Вы обязаны использовать хранимые процедуры и курсоры последовательно. Вы не можете их перемешивать. Исходя из этого, Вы обязаны дать системе знать, что Вы закончили использование хранимой процедуры, прежде чем сможете работать с курсором. Это выполняется через вызов метода returnValue объекта хранимой процедуры. Этот метод выдаёт return-значение хранимой процедуры (если она его имеет) и завершает выполнение хранимой процедуры. Вы должны также закрыть все объекты, относящиеся к хранимым процедурам, когда завершаете их использование.
ПРИМЕЧАНИЕ:
Для DB2, ODBC и Sybase Вы обязаны запросить resultSet -объекты до вызова метода returnValue. После того как Вы вызвали returnValue, Вы больше не сможете получить данные из результирующего набора и не сможете получить какие-либо дополнительные результирующие наборы. Вы должны вызывать returnValue после того, как обработали результирующий набор, но до запроса параметров вывода.
Работа с Результирующими Наборами
Этот этап применяется ко всем хранимым процедурам.
Как указано в разделе , разные БД возвращают результирующие наборы разными способами. Например, у Вас имеется таблица CUSTINFO со столбцами id, city и name. В Sybase Вы можете использовать такую процедуру для получения первых 200 рядов таблицы:
create proc getcusts as begin select id, name, city from custinfo where custno < 200 end
Если CUSTINFO является таблицей Informix, эквивалентная процедура в Informix может быть:
create procedure getcusts returning int, char(15), char(15);
define rcity, rname char (15); define i int;foreach select id, name, city into i, rname, rcity from custinfo where id < 200;
return i, rname, rcity with resume; end foreach; end procedure;
Если CUSTINFO - таблица Oracle, эквивалентная процедура Oracle может быть:
create or replace package orapack as type custcurtype is ref cursor return custinfo%rowtype end orapack;create or replace custresultset (custcursor inout orapack.custcurtype) as begin open custcursor for select id, name, city from custinfo where id < 200
end custresultset;
Во всех случаях Вы создаёте resultSet -объект для получения информации из хранимой процедуры. Вы делаете это через использование метода resultSet объекта хранимой процедуры так:
resObj = spObj.resultSet();
Как и для Cursor -объектов, resultSet -объекты содержат текущий ряд, то есть ряд, на котором стоит указатель в результирующем наборе. Вначале указатель позиционирован перед первым рядом результирующего набора. Чтобы увидеть значения рядов результирующего набора, Вы используете метод next для перемещения указателя по рядам результирующего набора, как показано в следующем примере:
spobj = connobj.storedProc("getcusts");
if ( spobj && (connobj.majorErrorCode() == 0) ) {
// Создаётся новый resultSet-объект. resobj = spobj.resultSet(); // Перед тем как продолжить, убедитесь, что Вы получили результирующий набор. if ( resobj && (connobj.majorErrorCode() == 0) ) { // Сначала перемещает указатель resultSet-объекта к первому // ряду результирующего набора, а затем циклически проходит по рядам. while (resObj.next()) { write("" + resObj.name + " ");
write("" + resObj.city + " ");
write("" + resObj.id + " "); }
resobj.close(); } }
До тех пор, пока в результирующем наборе имеется следующий ряд, метод next возвращает true и перемещает указатель к следующему ряду. Если указатель достиг последнего ряда результирующего набора, метод next возвращает false.
Предыдущий пример работает с хранимой процедурой Sybase. В этом случае resultSet -объект содержит именованное свойство для каждого столбца результирующего набора. Для процедур Informix и DB2, по контрасту, объект не содержит именованных столбцов. В этом случае Вы можете получить значения, ссылаясь на позицию столбца. Так, для Informix и DB2 Вы можете использовать такой код для вывода аналогичной информации:
spobj = connobj.storedProc("getcusts");
if ( spobj && (connobj.majorErrorCode() == 0) ) { // Создаётся новый resultSet-объект. resobj = spobj.resultSet();
// Перед тем как продолжить, убедитесь, что Вы получили результирующий набор.
if ( resobj && (connobj.majorErrorCode() == 0) ) {
// Сначала перемещает указатель resultSet-объекта к первому // ряду результирующего набора, а затем циклически проходит по рядам. while (resObj.next()) {
write("" + resObj[1] + " "); write("" + resObj[2] + " "); write("" + resObj[0] + " "); } resobj.close(); } }
Вы можете использовать позицию столбца для результирующих наборов любой БД, а не только с Informix и DB2. Вы можете использовать имя столбца для хранимой процедуры всех типов БД, а не только Informix или DB2.
Работа с Внешними Библиотеками
Для взаимодействия с внешними приложениями рекомендуется использовать LiveConnect, как описано в . Однако Вы можете также вызывать функции, написанные на других языках, таких как C, C++ или Pascal, и скомпилированных в библиотеки. Такие функции называются native-функции или внешние функции. Библиотеки внешних функций, называемые внешними библиотеками, являются библиотеками динамической компоновки/dll в ОС Windows и совместно используемыми объектами/shared objects - в ОС Unix.
Важно! Будьте осторожны при использовании внешних функций в Вашем приложении. Внешние функции могут нарушить защиту/безопасность, если внешняя программа выполняет команды пользователя в командной строке (например, программа, дающая возможность войти в ОС, или команды оболочки/shell). Эта функциональность опасна, так как хакер может присоединить дополнительные команды, используя точку с запятой для присоединения нескольких операторов. Лучше исключить использование ввода командной строки, если Вы не проверяете его достаточно жёстко.
Внешние функции используются в следующих случаях:
Если у Вас уже имеются сложные функции, написанные на других языках, которые можно использовать в приложении.
Если приложению нужны функции интенсивных вычислений. Обычно функции, написанные в native-коде, работают быстрее, чем функции, написанные на языке JavaScript.
Если приложение должно выполнять задачи, которые невозможно выполнить в JavaScript.
В директории примеров jsaccall есть несколько исходных и header-файлов, иллюстрирующих вызов функций внешних библиотек из приложения JavaScript.
В Application Manager Вы ассоциируете внешнюю библиотеку с
определённым приложением. Но после того как библиотека ассоциирована с одним из приложений, она становится доступной всем другим установленным приложениям.
Выполните следующие действия для использования библиотеки внешних функций в приложении JavaScript:
Напишите и скомпилируйте библиотеку внешних функций в форме, совместимой с JavaScript. (См. ) .С помощью Application Manager идентифицируйте используемую библиотеку, установив новое приложение или изменив параметры установки существующего приложения. После этого все приложения на данном сервере смогут вызывать внешние функции этой библиотеки. (См. ) .Рестартуйте сервер, чтобы загрузить библиотеку с Вашим приложением. Функции внешней библиотеки теперь доступны для всех приложений на этом сервере.
В вашем приложении используйте функции JavaScript registerCFunction - для идентифицирования вызываемых функций библиотеки - и callC - для вызова этих функций. (См. и ) .
Рекомпилируйте и рестартуйте Ваше приложение, чтобы изменения вступили в силу.
Важно!
Вы обязаны рестартовать Ваш сервер, чтобы установить библиотеку для использования с приложениями. Вы обязаны рестартовать сервер каждый раз после добавления файлов новых библиотек или изменения имён файлов библиотек, используемых приложениями.
Работа со Столбцами
Метод columns класса Cursor возвращает количество столбцов в курсоре. Этот метод не принимает параметров:
custs.columns()
Вы можете использовать этот метод, если нужно итерировать по каждому столбцу курсора.
Метод columnName класса Cursor возвращает имя столбца виртуальной таблицы. Этот метод принимает параметр - целое число, специфицирующее порядковый номер столбца, начиная с 0. Первым столбцом виртуальной таблицы является столбец 0, вторым - столбец 1, и так далее.
Например, следующее выражение присваивает имя первого столбца курсора custs переменной header:
header = custs.columnName(0)
Если Ваш оператор SELECT использует шаблон (*) для выбора всех столбцов таблицы, метод columnName не гарантирует, что порядок присвоения номеров столбцам будет тем же. То есть, предположим, у Вас есть оператор:
custs = connobj.cursor ("select * from customer");
Если таблица customer имеет 3 столбца, ID, NAME и CITY, Вы не сможете заранее предугадать, который из этих столбцов будет custs.columnName(0). (Конечно, есть гарантия, что последовательные вызовы columnName дадут аналогичный результат). Если порядок для Вас важен, можно жёстко кодировать имена в операторе выборки, как здесь:
custs = connobj.cursor ("select ID, NAME, CITY from customer");
В этом операторе, custs.columnName(0) это ID, custs.columnName(1) это NAME, а custs.columnName(2) это CITY.
Регистрация Хранимой Процедуры
Этот этап выполняется только в DB2.
В DB2 имеются различные системные таблицы, в которые Вы можете записать Вашу хранимую процедуру. В общем, вставка хранимой процедуры в эти таблицы не обязательна. Однако, для того чтобы использовать Вашу хранимую процедуру с LiveWire, Вы обязаны создать вхождения в этих таблицах. Этот этап выполняется вне приложения JavaScript.
Для обычного DB2-сервера Вы обязаны создать системную таблицу DB2CLI.PROCEDURES и ввести в неё Ваши DB2-хранимые процедуры. DB2CLI.PROCEDURES это таблица-псевдокаталог.
Если Ваш DB2 предназначен для IBM MVS/EA версии 4.1 или более поздней, Вы обязаны определить имена Ваших хранимых процедур в таблице-каталоге SYSIBM.SYSPROCEDURES.
Не забывайте, что Вы используете C, C++ или другой язык для написания DB2-хранимой процедуры. Типы данных, которые Вы используете в этих языках, не соответствуют типам данных, доступным в DB2. Следовательно, если Вы добавляете хранимую процедуру в DB2CLI.PROCEDURES или в SYSIBM.SYSPROCEDURES, убедитесь, что записаны соответствующие типы данных DB2 для параметров хранимой процедуры, а не типы данных исходных языков.
Информацию о типах данных DB2 и о том, как сделать вхождения в таблицах, см. в документации по DB2.
Регистрация Внешних Функций
Используйте JavaScript-функцию registerCFunction для регистрации внешней функции для использования с приложением JavaScript. Эта функция имеет следующий синтаксис:
registerCFunction(JSFunctionName, libraryPath, CFunctionName);
Здесь JSFunctionName это имя функции как она будет вызываться в JavaScript функцией callC. Параметр libraryPath это полный путь к библиотеке, использующий соглашения Вашей ОС, а параметр CFunctionName это имя C-функции как она определена в библиотеке. В вызове этого метода Вы обязаны вводить имя точно в указанном регистре, указанном в Application Manager, даже в ОС NT.
ПРИМЕЧАНИЕ:
Backslash (\) это специальный символ в JavaScript, поэтому Вы обязаны использовать forward slash (/) или двойной backslash (\\) для отделения Windows-директории и имён файлов в libraryPath.
Данная функция возвращает true, если функция зарегистрирована успешно, и false - в ином случае. Функция может потерпеть неудачу, если JavaScript не сможет найти библиотеку по специфицированному пути или не найдёт специфицированную функцию в библиотеке.
Приложение обязано использовать registerCFunction для регистрации функции, прежде чем сможет использовать callC для её вызова. После того как приложение зарегистрировало функцию, оно может вызывать эту функцию любое число раз. Хорошим местом для регистрации функций является начальная страница приложения.
Рекомендации по Написанию Внешних Функций
Хотя Вы можете написать внешние библиотеки на любом языке, JavaScript использует соглашения языка C по вызову. Ваш код обязан подключать header-файл jsaccall.h, находящийся в директории js\samples\jsaccall\.
Эта директория также содержит исходный код примеров приложений, которые вызывают функции C, определённые в jsaccall.c. Просмотрите эти файлы, чтобы найти более конкретные рекомендации по написанию функций C для использования с JavaScript.
Функции, вызываемые из JavaScript, обязаны быть экспортируемыми и обязаны соответствовать этому определению типа:
typedef void (*LivewireUserCFunction) (int argc, struct LivewireCCallData argv[], struct LivewireCCallData* result, pblock* pb,
Session* sn, Request* rq);
Return-Значения
Как и вызов функции, хранимая процедура может иметь возвращаемое/return значение. Для Oracle и Sybase это return-значение является дополнением к возвращаемому результирующему набору.
Метод returnValue класса Stproc используется для доступа к return-значению. Однако return-значения для хранимой процедуры Informix используются для генерации её результирующего набора. Поэтому returnValue всегда возвращает null для хранимых процедур Informix. Помимо этого, return-значения недоступны для хранимых процедур ODBC и DB2.
Return-значение методов объектов LiveWire может указывать, имеется ошибка или нет. Методы могут возвращать значения различных типов. В зависимости от типа Вы можете получать различную информацию о возможных ошибках.
Результирующие Наборы
Хранимая процедура может выполнять один или более операторов SELECT, запрашивая информацию из БД. Вы можете представить эту информацию как виртуальную таблицу, очень похожую на курсор "только для чтения". (О курсорах см. раздел ).
LiveWire использует класс Resultset как контейнер рядов, возвращаемых одним оператором SELECT хранимой процедуры. Если хранимая процедура допускает наличие нескольких операторов SELECT, Вы получите отдельные объекты Resultset для каждого оператора SELECT. Метод resultSet класса Stproc используется для получения результирующего набора объектов, а затем методы этих объектов используются для манипулирования результирующим набором.
БД различных производителей возвращают результирующий набор по-разному:
Хранимые процедуры Sybase могут напрямую возвращать результат выполнения одного или более операторов SELECT.
Хранимые процедуры Informix могут иметь несколько return-значений. Несколько return-значений подобны столбцам одного ряда таблицы, за исключение того, что эти столбцы именованы. Кроме того, если Вы используете возможность RESUME, хранимая процедура может иметь набор этих return-значений. Это набор напоминает ряды таблицы. LiveWire создаёт один результирующий набор для вмещения этой виртуальной таблицы.Хранимые процедуры Oracle используют ref-курсоры для вмещения рядов, возвращаемых оператором SELECT. Вы можете открыть несколько ref-курсоров в хранимой процедуре Oracle, чтобы вместить ряды , возвращаемые разными операторами SELECT. LiveWire создаёт отдельные Resultset -объекты для каждого ref-курсора.
Хранимые процедуры DB2 используют открытые курсоры для возвращения результирующих наборов.
Roll back/откат
Отмена всех акций в БД в пределах выполнения одной транзакции.
Сбор Мусора
Серверный JavaScript имеет сборщика мусора, который автоматически освобождает память, выделенную для объекта, более не используемого. В большинстве случаев нет необходимости понимать досконально работу сборщика мусора. Этот раздел даёт обзор сборщика мусора и информацию о том, когда он вызывается.
Важно!
Этот раздел даёт возможность продвинутым пользователям взглянуть на внутренние процессы JavaScript. Netscape не гарантирует, что эти алгоритмы останутся такими же в последующих релизах.
Пространство объекта в JavaScript состоит из арен. То есть машина выполнения JavaScript размещает набор арен, из которого затем размещает объекты. Если машина выполнения получает запрос на новый объект, она сначала просматривает список свободных арен. Если в списке свободных есть место, машина выделяет его. Иначе машина выполнения выделяет место в текущей используемой арене. Если используются все арены, машина размещает новую арену. Если все объекты арены - мусор, сборщик мусора освобождает арену.
Строка JavaScript обычно размещается как GC-объект. Строка имеет ссылку на байты строки, которая также размещается в куче/heap процесса. Если строковой объект подвергся сборке мусора, байты строки высвобождаются.
Работа сборщика мусора JavaScript основана на пометке и уничтожении. Сборщик не перемещает объекты. Он всегда обрабатывает корневой набор объектов. Этот корневой набор/root set включает в себя стэк JavaScript, объект global для контекста JavaScript и любые объекты JavaScript, которые были явно добавлены в корневой набор. В фазе разметки сборщик мусора помечает все объекты, достижимые из корневого набора. В конечной фазе все непомеченные объекты уничтожаются. Все убранные объекты собираются в список свободных.
Сборка мусора считается необходимой, если количество текущих используемых байтов в 1.5 раза превышает количество байтов, бывших в использовании в конце последней уборки мусора. Машина выполнения проверяет это условие в следующих точках и начинает уборку, если это необходимо:
В конце каждого запроса.
Во время длительных вычислений JavaScript после предопределённого количества выполненных операций с байт-кодами JavaScript и только когда выполняется операция ветвления. Если у Вас код без операций ветвления, сбор мусора не происходит просто оттого, что выполняется предопределённое количество операций. (Операция ветвления/branch может быть в операторах if, while, вызове функции и т.п.) .Когда делается попытка разместить новый объект JavaScript, но в JavaScript нет свободной памяти и дополнительная память не может быть получена от операционной системы.
Если вызывается функция lw_ForceGarbageCollection.
Server cookie/серверная кука
Один из видов техники JavaScript для обслуживания объекта client, когда сервер генерирует уникальное имя для клиента, сохраняемое в cookie-файле на стороне клиента и позднее использует сохранённое имя для обращения к структуре данных, содержащей значения свойств объекта client.
Server-side JavaScript/серверный JavaScript
Ядро JavaScript плюс расширения, относящиеся только к работе JavaScript на сервере. Например, серверные расширения дают приложению возможность соединяться с реляционной БД, сохранять непрерывность информации от одного вызова приложения до другого или выполнять манипуляции с файлами на сервере. См. также , .
Server URL encoding/серверная кодировка URL
Один из видов техники JavaScript для обслуживания объекта client, когда сервер генерирует для клиента уникальное имя, присоединяет его к URL и позднее использует сохранённое имя для обращения к структуре данных, содержащей значения свойств объекта client.
Серверная Техника
Есть три вида серверной техники:
IP-адресаСерверные куки
Серверное кодирование URL
Сравнение разных видов техники см. в разделе .
При любом виде техники машина выполнения на сервере сохраняет свойства объекта client и их значения в структуре данных в памяти сервера. Единая структура данных, сохраняемая в период между клиентскими запросами, используется для всех приложений, работающих на сервере. Виды техники различаются только в индексе, используемом для доступа к информации в этой структуре данных, гарантируя, что каждая пара клиент/приложение получает соответствующие свойства и значения для объекта client.
Ни одна из этих техник не записывает информацию на жёсткий диск сервера. Только техника серверных кук позволяет записывать информацию на диск клиентской машины при окончании работы браузера.
Поскольку эти виды техники сохраняют информацию объектов client в памяти сервера в промежутке между клиентскими запросами, нет или почти нет увеличения сетевого трафика. Имена и значения свойств никогда не пересылаются клиенту. Кроме того нет ограничения на количество свойств объекта client и на размер свойства.
Недостатком является, разумеется, то, что эти виды техники используют память сервера в промежутке между клиентскими запросами. Для приложений, используемых большим количеством потребителей, это может иметь важное значение. Конечно, это можно также рассматривать и как преимущество, так как Вы можете сохранять столько информации, сколько необходимо.
Серверный JavaScript 1.4. Руководство по Использованию.
Перевод выполнил Александр Пирамидин.
Прошу все замечания и предложения направлять по e-mail:
В этой книге рассматривается использование ядра и серверного JavaScript версии 1.4. JavaScript это созданный фирмой Netscape межплатформенный объектно-ориентированный язык скриптов (сценариев) для клиентских и серверных приложений.
Серверный JavaScript
На сервере Вы также можете внедрять JavaScript в HTML-страницы. Серверные операторы могут соединяться с реляционными БД разных производителей, разделять информацию между пользователями приложения, получать доступ к файловой системе сервера или взаимодействовать с другими приложениями через LiveConnect и Java. HTML-страницы с серверным JavaScript могут содержать также клиентский JavaScript.
В отличие от страниц с чисто клиентским JavaScript, HTML-страницы, использующие серверный JavaScript, компилируются в байт-кодовые исполняемые файлы. Эти исполняемые приложения запускаются на выполнение web-сервером, имеющим машину времени выполнения JavaScript. Исходя из этого, создание приложений JavaScript это процесс из двух этапов.
На первом этапе, показанном на , Вы создаёте HTML-страницы (которые могут содержать операторы как клиентского, так и серверного JavaScript) и файлы JavaScript. Затем Вы компилируете все эти файлы в единый исполняемый блок.
Рисунок 1.3 Серверный JavaScript в процессе разработки
На втором этапе, показанном на , страница приложения запрашивается клиентским браузером. Машина выполнения использует исполняемый блок для просмотра исходной страницы и динамической генерации HTML-страницы, возвращаемой клиенту. Она выполняет все найденные на странице операторы серверного JavaScript. Выполнение этих операторов может добавить новые операторы HTML или операторы клиентского JavaScript в HTML-страницу. Машина выполнения отсылает затем окончательный вариант страницы по сети Navigator-клиенту, который выполняет клиентский JavaScript и отображает результат.
Рисунок 1.4 Серверный JavaScript в процессе выполнения
В отличие от стандартных программ Common Gateway Interface (CGI), все исходники JavaScript интегрированы непосредственно в HTML-страницы, ускоряя разработку и облегчая обслуживание. Служба Session Management Service серверного JavaScript содержит объекты, которые Вы можете использовать для работы с данными, существующими между клиентскими запросами, у нескольких клиентов или нескольких приложений. Служба LiveWire Database Service серверного JavaScript предоставляет объекты для доступа к БД, служащие интерфейсом для серверов Structured Query Language (SQL).
Серверный Язык. Обзор.
И клиентский, и серверный JavaScript реализуют язык JavaScript. Но каждый при этом добавляет специфические объекты и функции для работы в клиентской или серверной среде. Например, клиентский JavaScript включает объект form для представления формы на HTML-странице, а серверный JavaScript включает объект database для соединения с внешней реляционной БД.
В книге
Клиентский JavaScript. Руководство. детально рассматривается ядро языка JavaScript и дополнительная специфика клиентского JavaScript.
ECMA, Европейская организация стандартизации систем информации и коммуникаций, выпустила стандарт ECMA-262 языка JavaScript. Вы можете загрузить эту спецификацию с сайта ECMA по адресу .
Session Management Service/Служба Обслуживания Сессий
4 предопределённых объекта JavaScript - request, client, project и server - и один класс, Lock, предоставляющие основу для совместного использования данных запросами, клиентами и приложениями.
Создание объекта request и конструирование или восстановление объекта client
Инициализируются встроенные свойства объекта request, такие как IP-адрес и элементы формы, ассоциированные с данным request. Если URL запроса специфицирует другие свойства, они инициализируются для объекта request, как описано в разделе .
Если объект client уже существует, машина выполнения запрашивает его на основе специфицированной техники обслуживания клиента. (См. ). Если объект client не существует, машина выполнения конструирует новый объект без свойств.
Вы не можете предвидеть, в каком порядке эти объекты конструируются.
Поиск исходной страницы и начало конструирования HTML-страницы
Когда Вы компилировали исходный код JavaScript, исходник включал HTML-страницы с операторами серверного JavaScript. Главной задачей машины выполнения является конструирование из одной из этих исходных страниц HTML-страницы, содержащей только HTML и операторы клиентского JavaScript. При создании этой HTML-страницы машина выполнения сохраняет её части в области памяти, называемой буфером, пока не придёт время отправки буферизованного содержимого клиенту.
Добавить в буфер вывода или выполнить код
Этот шаг выполняется для каждого участка кода исходной страницы. Детали процесса выполнения различных серверных операторов рассматриваются далее в этом учебнике. Дополнительно см. .
Для данного запроса/request машина выполнения выполняет этот шаг, пока не произойдёт одно из следующих событий:
Буфер содержит 64KB HTML.
В этой ситуации машина выполняет шаги 4 и 5 и возвращается к выполнению шага 3 с очищенным буфером, продолжая выполнение того же запроса. (Шаг 4 исполняется только один раз, даже если шаги 3 и 5 повторяются).
Сервер выполняет функцию flush.
В этой ситуации машина выполняет шаги 4 и 5 и возвращается к выполнению шага 3 с очищенным буфером, продолжая выполнять тот же самый запрос. (Шаг 4 исполняется только один раз, даже если шаги 3 и 5 повторяются).
Сервер выполняет функцию redirect.
В этой ситуации машина выполнения завершает данный запрос, выполняя шаги с 4 по 6. Она игнорирует любые вхождения после функции redirect в исходном файле и стартует новый запрос для страницы, специфицированной в вызове redirect.
Доходит до конца страницы.
В этой ситуации машина завершает данный запрос, выполняя шаги с 4 по 6.
Сохранение свойств объекта client
Машина выполнения сохраняет свойства объекта client непосредственно перед первой отправкой части HTML-страницы клиенту. Она сохраняет эти свойства только один раз. Машина выполнения может повторять шаги 3 и 5, но не может повторить данный шаг.
Машина выполнения сохраняет свойства в этот момент, чтобы поддерживать один из видов техники обслуживания объекта client. Например, схема кодирования клиентского URL высылает свойства client'а в шапке/header HTML-файла. Поскольку шапка высылается как первая часть файла, свойства client'а обязаны быть затем высланы.
Следовательно, Вы должны учитывать, где в Вашем файле-источнике устанавливаются свойства client'а. Вы всегда должны изменять свойства client'а в файле до любого вызова redirect или flush и до генерирования 64KB HTML-вывода.
Если Вы изменяете значения свойств объекта client в коде после того как HTML был выслан клиенту, эти изменения будут действовать для оставшейся части клиентского запроса, но затем будут отменены. Отсюда: следующий клиентский запрос не получит эти значения свойств; он получит значения, действовавшие в тот момент, когда содержимое было в первый раз отправлено клиенту. Например, ваш код содержит такие операторы:
The current customer is
client.customerName = "Mr. Ed"; write(client.customerName); client.customerName = "Mr. Bill";
The current customer really is
write(client.customerName);
Эта серия операторов даст в результате такой HTML, отправляемый клиенту:
The current customer is Mr. Ed The current customer really is Mr. Bill
Теперь, когда появится следующий клиентский запрос, значение свойства client.customerName будет "Mr. Bill". Этот очень похожий набор операторов даст в результате тот же HTML:
The current customer is
client.customerName = "Mr. Ed"; write(client.customerName); flush();
client.customerName = "Mr. Bill"; The current customer really is
write(client.customerName);
Однако при появлении следующего клиентского запроса значение client.customerName будет "Mr. Ed"; а не "Mr. Bill".
Дополнительно см. .
Отправка HTML клиенту
Сервер отсылает содержимое страницы клиенту. Для страниц без операторов серверного JavaScript сервер просто передаёт HTML клиенту. Для других страниц - машина выполнения реализует логику приложения для конструирования HTML и затем высылает сгенерированную страницу клиенту.
Уничтожение объекта request и сохранение или уничтожение объекта client
Машина выполнения разрушает объект request, сконструированный для данного клиентского запроса. Она сохраняет значения объекта client и разрушает физический объект JavaScript. Она не разрушает объекты project или server.
Шапка/Header Ответа
Если отправляемый клиенту ответ/response использует специальный content type (тип содержимого), Вы должны кодировать этот content type в шапке ответа. Машина выполнения JavaScript автоматически добавляет content type по умолчанию (text/html) в шапку ответа/response header. Если вам необходима специальная шапка, Вы обязаны сначала удалить из шапки старый content type по умолчанию, а затем уже добавить новый. Это делается при помощи функций addResponseHeader и deleteResponseHeader.
Например, если Ваш response использует royalairways-format как специальный content type, Вы можете специфицировать его так:
deleteResponseHeader("content-type");
addResponseHeader("content-type","royalairways-format");
Вы можете использовать функцию addResponseHeader для добавления в шапку ответа любой другой нужной информации.
Важно! Помните, что header отсылается с первой частью ответа/response. Следовательно, Вы должны вызывать эти функции раньше в скрипте на каждой странице. В общем, Вы должны быть уверены, что header ответа установлен до любого из следующих событий:
Машина выполнения сгенерировала 64KB содержимого для HTML-страницы (в этой точке буфер вывода автоматически очищается).
Вы вызываете функцию flush для очистки буфера вывода.
Вы вызываете функцию redirect для изменения клиентских запросов.
Дополнительно см. разделы и .
1
Шапка/Header Запроса
Для доступа к парам имя/значение шапки клиентского запроса используйте метод httpHeader объекта request. Этот метод возвращает объект, чьи свойства и значения соответствуют парам имя/значение шапки.
Например, если запрос содержит куки, header["cookie"] или header.cookie будет его значением. Свойство cookie, содержащее все пары имя/значение этой куки (со значениями, кодированными так, как описано в разделе ), обязано разбираться Вашим приложением.
Следующий код выводит свойства и значения шапки:
var header = request.httpHeader(); var count = 0; var i;
for (i in header ) {
write(count + ". " + i + " " + header[i] + " \n"); count++;
}
Если Вы отправили форму методом GET, на выходе получится примерно так:
0. connection Keep-Alive 1. user-agent Mozilla/4.0b1 (WinNT; I)
2. host piccolo:2020 3. accept image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Если для отправки формы использован метод POST, вывод будет таким:
0. referer http://piccolo:2020/world/hello.html
1. connection Keep-Alive 2. user-agent Mozilla/4.0b1 (WinNT; I) 3. host piccolo:2020
4. accept image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
5. cookie NETSCAPE_LIVEWIRE.oldname=undefined; NETSCAPE_LIVEWIRE.number=0
6. content-type multipart/form-data; boundary=---------------------------79741602416605
7. content-length 208
Системные Требования
Чтобы разрабатывать приложения JavaScript, использующие преимущества и клиентского, и серверного JavaScript, Вам нужна подходящая среда для разработки и публикации. В целом рекомендуется разрабатывать приложения на системе, отделённой от сервера публикации, поскольку разработка потребляет много ресурсов (порты соединений, пропускная способность, время процессора и память). При разработке также может быть нарушена работа уже опубликованных приложений конечного пользователя.
Среда разработки JavaScript состоит из:
Утилит для авторизации и компиляции приложений JavaScript. Эти утилиты обычно находятся на машине разработчика.
Машины разработчика с web-сервером для запуска приложений JavaScript, находящихся в стадии разработки. Машины публикации с web-сервером для публикации разработанных приложений. Конечные пользователи осуществляют доступ к приложениям, находящимся на этом сервере.
Необходимые утилиты:
Браузер с возможностью выполнения JavaScript, такой как Netscape Navigator, входящий в состав Netscape Communicator.
Компилятор приложений JavaScript, такой как компилятор web-серверов Netscape.
Редактор, такой как Emacs или Notepad.
Публикация и машины публикации требуют наличия следующего программного обеспечения:
Web-сервера;
Машины выполнения JavaScript, такой как машина web-серверов Netscape.
Возможности конфигурирования Вашего сервера для работы приложений JavaScript, как это сделано в JavaScript Application Manager, поставляемом вместе с web-серверами Netscape.
Кроме того, если ваше приложение использует JavaScript-службу LiveWire Database Service, Вам понадобится:
Программа - сервер реляционных БД на Вашей машине-сервере БД. См. документацию вашего сервера БД. В некоторых случаях Вам понадобится установить web-сервер и сервер БД на одной машине. О специфических требованиях серверного JavaScript см. Клиент БД и сетевое программное обеспечение на машине Вашего web-сервера. Если Вы используете одну машину и как сервер БД, и как web-сервер, типичное клиентское обеспечение БД как правило уже установлено при установке сервера БД. В противном случае Вам нужно удостовериться, что клиент БД установлен на той же машине, что и web-сервер, чтобы можно было иметь доступ к БД как клиент. О требованиях к клиентскому программному обеспечению см. дополнительно документацию поставщика БД.
Словарь
Здесь определены термины, используемые в приложениях JavaScript.
Служба Файловой Системы
JavaScript предоставляет класс File, который даёт приложению возможность записывать в файловой системе сервера. Это используется для генерации постоянных HTML-файлов и хранения информации без использования сервера БД. Одним из важнейших преимуществ хранения информации в файле вместо JavaScript-объектов является то, что информация сохраняется даже при отказе сервера.
Соединение и Процесс Работы
Когда пользователь инициирует сессию с приложением videoapp, входя на начальную страницу (home.htm), videoapp проверяет, имеется ли уже соединение с БД. Если это так, videoapp предполагает, что не только приложение, но и пользователь уже соединены с БД, и продолжает работу.
Если соединение не установлено, videoapp перенаправляет на страницу start.htm. На ней приложение создаёт единый пул соединений с БД, используемый всеми потребителями, получает соединение для пользователя и стартует транзакцию с БД для этого соединения. Затем перенаправляет обратно на home.htm для продолжения. Пользователь никогда не видит перенаправления.
Транзакция базы данных стартует на странице start.htm и остаётся открытой, пока пользователь явно не сохранит или не отменит изменения, щёлкнув кнопку Save Changes или Abort Changes. При этом запускается save.htm или abort.htm. Эти страницы подтверждают или откатывают изменения открытой транзакции, а затем немедленно начинают новую транзакцию. Поэтому соединение потребителя всегда остаётся открытым.
Получив соединение с БД, videoapp выводит пользователю главную страницу. С неё пользователь может сделать выбор - такой как аренда клипа или добавление нового потребителя. Каждая из этих опций выводит разные страницы, которые содержат операторы серверного JavaScript. Многие страницы имеют операторы, использующие соединение для взаимодействия с БД, выводя информацию или внося изменения в БД.
Первое, что Вы обязаны сделать при первом соединении, это добавить нового потребителя. Пока Вы этого не сделаете, отсутствуют потребители для выполнения других действий программы.
Соединение. Подходы.
Есть два основных способа соединения с БД с помощью сервиса LiveWire Database Service. Это объекты DbPool и Connection, либо объект database.
Соединение с БД и Рекомпиляция
Приложение videoapp находится в директории $NSHOME\js\samples\videoapp, где $NSHOME это директория установки Netscape-сервера. Приложение oldvideo находится в директории $NSHOME\js\samples\oldvideo.
Для каждого приложения Вы обязаны изменить строку с информацией о соединении в исходном HTML-файле start.htm, чтобы настроиться на среду окружения Вашей БД. О параметрах соединения см. раздел ; дополнительно см. также описание метода connect в книге
.
Для приложения videoapp измените эту строку:
project.sharedConnections.pool =
new DbPool ("", "", "", "", "", 2, false)
Для приложения oldvideo измените эту строку:
database.connect ("INFORMIX", "yourserver", "informix", "informix", "lw_video")
Сохраните изменения и рекомпилируйте приложение. Для рекомпиляции приложения из командной строки запустите его build-файл, расположенный в директории приложения. Убедитесь, что переменная окружения PATH содержит путь к компилятору (обычно это $NSHOME\bin\https).
Рестартуйте приложения в JavaScript Application Manager'е.
Соединение с Объектом database
При этом подходе Вы используете предопределённый объект database для соединения с БД при наличии единственной конфигурации соединения БД и пользователя. Объект database выполняет все действия по работе с БД. Можно представить этот объект как database единый пул соединений с БД.
Этот подход несколько проще, так как используется только один объект database, а не несколько объектов DbPool и Connection. Однако при этом теряется гибкость первого подхода. Если Вы используете только объект database и хотите соединиться с разными БД или разными бюджетами, Вы обязаны отключиться от одной конфигурации, для того чтобы подключиться к другой. Также, при использовании объекта database, одна транзакция не может захватить несколько клиентских запросов, а соединения с несколькими БД-источниками не могут быть установлены одновременно.
Как описано в последующих разделах, Вы должны ответить на два основных вопроса, когда решаете, как устанавливать соединения с БД:
Сколько конфигураций и соединений БД и пользователей Вам нужно?
Будет ли одно соединение захватывать несколько клиентских запросов?
В таблице резюмируется, как ответ на эти вопросы влияет на установку и обслуживание пула соединений с БД и отдельных соединений. В последующих разделах обсуждаются детали этих вариантов.
Сколько конфигураций БД?
Где соединение с пулом?
Где отключение пула?
Какой объект(ы) содержит пул?
Должен ли Ваш код хранить пул и соединение?
Как Ваш код хранит пул и соединение в объекте project?
1, используется всеми клиентами
Начальная страница приложения Нигде database Нет -- 1, используется всеми клиентами Начальная страница приложения Нигде 1 DbPool object Да DbPool: Именованное свойство;
Connection: 1 массив
Фиксированный набор, используется всеми клиентами
Начальная страница приложения Нигде N DbPool-объектов Да DbPool: Именованное свойство;
Connection: N массивов
Отдельный пул для каждого клиента
Клиентская страница запроса Зависит от Многие объекты DbPool
Только если соединение захватывает клиентские запросы
DbPool: 1 массив;
Connection: 1 массив
1
Если отдельное соединение не захватывает клиентские запросы, Вы можете соединять и отсоединять пул на каждой странице, в которой нужнó соединение. В этом случае пул не сохраняется в промежутке времени между запросами. Если отдельное соединение захватывает клиентские запросы, соединяйте на первой клиентской странице, которой необходимо соединение, и отсоединяйте на последней такой странице. Это может привести к появлению незанятых соединений/idle, и Ваше приложение должно будет обработать такую ситуацию.
Соединение с Помощью Объектов DbPool и Connection
При этом подходе Вы создаёте пул соединений для работы с реляционной БД. Вы создаёте экземпляр класса DbPool,а затем получаете доступ к объектам Connection через этот объект DbPool. Объекты DbPool и Connection распределяют между собой работу по соединению с БД и обслуживанию набора соединений и доступ к БД через соединение.
Это весьма гибкий подход. Ваше приложение может иметь несколько пулов соединений, каждый со своей собственной конфигурацией БД и пользователя. Каждый пул может иметь несколько соединений при такой конфигурации. Это даёт одновременный доступ к нескольким БД или к одной БД из нескольких бюджетов. Вы можете также ассоциировать пул непосредственно с приложением, а не с отдельным клиентским запросом, и иметь таким образом транзакции, захватывающие несколько клиентских запросов. Это ассоциирование выполняется путём присвоения пула свойству объекта project и удаления этого присвоения после окончания работы с пулом.
Соглашения по Документам
Приложения JavaScript работают на многих операционных системах; данная информация применима ко всем версиям. Пути файлов и директорий даны в формате Windows (с обратной наклонной чертой в качестве разделителя имён директорий). Для Unix-версий пути директорий - те же, за исключением того, что в качестве разделителей используются слэши вместо backslash.
В этой книге используются uniform resource locators (URLs) в форме:
http://server.domain/path/file.html
В этих URL server это имя сервера, на котором запускается Ваше приложение, как, например, research1 или www; domain это имя домена Internet, такое как netscape.com или uiuc.edu; path это структура директорий на сервере; а file.html это имя файла. В целом элементы, выделенные italic в URL, являются заглушками, а элементы с нормальным моноширинным шрифтом являются литералами. Если на Вашем сервере имеется Secure Sockets Layer (SSL), Вы должны использовать https вместо http в URL.
В книге использованы следующие соглашения по шрифтам:
Моноширинный шрифт используется в примерах кода, API и элементах языка (таких как имена функций и классов), именах файлов, путях, именах директорий, тэгах HTML и в любом тексте, который должен выводиться на экран монитора. (Моноширинный italic используется для заглушек, вставленных в код.) Italic-шрифт
используется в названиях книг, при выделении текста, в переменных и заглушках и в словах, используемых в литеральном смысле.
Жирный шрифт используется в терминах словаря.
Дата последнего обновления: 29 сентября 1999 г.
© Copyright © 1999 Sun Microsystems, Inc. Некоторая часть Copyright © 1999 Netscape Communications Corp. Все Права Зарезервированы.
Сообщение Между Сервером и Клиентом
Нередко Вашим приложениям JavaScript нужно передать информацию либо с сервера клиенту, либо с клиента на сервер. Например, когда пользователь в первый раз выполняет доступ к приложению videoapp, оно динамически генерирует список категорий видео-файлов из текущего содержимого БД. Эта информация, генерируемая на сервере, должна быть передана обратно клиенту. И наоборот, когда пользователь щёлкает на категории из этого списка, выбор пользователя должен быть передан обратно на сервер, чтобы он мог сгенерировать набор файлов.
Соотношение Между Версиями JavaScript и ECMA
Netscape тесно сотрудничает с ECMA для создания спецификации ECMA.
Детальную информацию о соотношении версий спецификаций JavaScript и ECMA см. на сайте mozilla.org.
JavaScript всегда будет содержать возможности, не включённые в спецификацию ECMA; JavaScript совместим с ECMA, предоставляя дополнительные возможности.
Эти указания являются критичными для
Эти указания являются критичными для однопоточного доступа. Однако Вы должны думать об этом даже тогда, когда используете БД с многопоточным доступом.
Однопоточная библиотека БД может иметь существенные ограничения производительности. Поскольку только один поток имеет доступ к БД в единицу времени, все прочие потоки обязаны ждать, когда первый поток освободит соединение с БД, прежде чем один из них сможет получить доступ к БД. Если доступа ожидают одновременно несколько потоков, каждому придётся ожидать довольно долго.
При разработке доступа к БД Вы должны предусмотреть следующее:
Старайтесь максимально сократить взаимодействие с БД.
Каждый поток обязан ждать окончания работы другого потока. Чем короче время взаимодействия с БД, тем меньше ожидание.
Всегда освобождайте соединение сразу и закрывайте открытые курсоры и хранимые процедуры.
Вы должны делать это в любом случае. Но в случае с однопоточной БД это становится абсолютно необходимым для предотвращения ожидания.
Всегда используйте явное управление транзакциями.
Тогда будет ясно, когда завершена работа с соединением.
Не держите соединение открытым, ожидая ввода от пользователя.
Пользователи не всегда завершают начатое. Если пользователь сделал переход от Вашего приложения, когда соединение с БД открыто, система не должна заботиться об освобождении этого соединения. Если только Вы не реализуете схему с запросом незанятых соединений (как указано в разделе ), такое соединение может оказаться связанным на достаточно продолжительное время, ограничивая таким образом доступ других пользователей к БД.
Не оставляйте курсоры и транзакции открытыми для нескольких страниц Вашего приложения.
Когда взаимодействие с БД захватывает несколько страниц приложения, риск того, что пользователь не завершит транзакцию, значительно возрастает.
Ограничения на использование транзакций для клиентских библиотек БД, которые не являются многопоточными:
Если у Вас однопоточные библиотеки и Вы используете два соединения одновременно на одной странице с БД одного типа, Вы можете получить deadlock/мёртвую блокировку, если выполняете явные транзакции (то есть такие, которые начинаются с использования beginTransaction). Это может случиться с транзакциями на одной странице.
При многостраничных транзакциях с однопоточными библиотеками только одно соединение с БД может быть активным в единицу времени, или Вы получите мёртвую блокировку, как описано в предыдущем пункте.
Если клиентская библиотека БД не является многопоточной, только одна соединение с БД может быть активным в единицу времени. Хотя Вы не обязаны изменять свой код для обработки такой ситуации, Вы должны знать, что без многопоточной клиентской библиотеки БД Вы не получите выигрыша в производительности, даваемого многопоточными библиотеками при наличии нескольких одновременных соединений.
Некоторые библиотеки БД не являются многопоточными. По этой причине, если Вы используете объекты database() или DbPool(), Вы обязаны установить максимальное допустимое количество соединений с БД в Вашем приложении большим, чем количество клиентов, которые, как Вы предполагаете, будут использовать Ваше приложение. Иначе некоторые клиенты не смогут установить соединение с БД, и их приложения зависнут.
Совместное Использование Фиксированного Набора Пулов Соединений
Часто в приложении небольшой набор пулов соединений используется всеми пользователями данного приложения. Например, Вашему приложению нужно соединяться с тремя различными БД или с одной БД, которая использует 4 пользовательских ID, соответствующих 4 разным департаментам. Если у вас имеется небольшой набор возможных конфигураций соединения, Вы можете создать отдельный пул для каждой конфигурации. Для этого используйте объекты DbPool.
Тогда необходимо, чтобы пул работал в течение всего периода существования приложения, а не просто в течение периода существования клиента или отдельного клиентского запроса. Вы можете реализовать это, создав каждый пул БД как свойство объекта project. Например, начальная страница приложения может содержать эти операторы:
project.engpool = new DbPool ("ORACLE", "myserver1", "ENG", "pwd1", "", 5, true); project.salespool = new DbPool ("INFORMIX", "myserver2", "SALES", "pwd2", "salsmktg", 2); project.supppool = new DbPool ("SYBASE","myserver3","SUPPORT", "pwd3", "suppdb", 3, false);
Эти операторы создают три пула для различных групп пользователей приложения.
Пул project.eng содержит 5 соединений Oracle и подтверждает любую неподтверждённую транзакцию при высвобождении соединения обратно в пул.
Пул project.sales имеет два соединения Informix и откатывает любую неподтверждённую транзакцию при окончании соединения.
Пул project.supp имеет три соединения Sybase и откатывает любую неподтверждённую транзакцию при окончании соединения.
Вы должны создавать такой пул как часть начальной страницы приложения. Эта страница выполняется только при старте приложения. На страницах, доступных пользователям, Вы не создаёте пул и не изменяете соединение. Вместо этого эти страницы определяют, к какой группе принадлежит текущий пользователь, и используют уже установленное соединение из соответствующего пула. Например, в следующем коде определяется, какую БД использовать (на основе значения свойства userGroup объекта request), в БД ищется некоторая информация, которая выводится пользователю, а затем соединение освобождается:
if (request.userGroup == "SALES") { salesconn = project.salespool.connection("A sales connection"); salesconn.SQLTable ("select * from dept"); salesconn.release(); }
Вы можете также создать пул и изменить соединение на странице, доступной пользователю. В этом случае Вы должны быть осторожны, так как несколько пользователей, осуществляющих одновременный доступ к этой странице, не должны мешать друг другу. Например, только один пользователь должен иметь возможность создавать пул, используемый всеми остальными пользователями. О надёжности совместного использования информации см. раздел .
Совместное Использование Массива Пулов Соединений
В разделе описано, как Вы можете применить свойства объекта project для совместного использования фиксированного набора пулов соединений. Этот подход используется, если Вам в процессе разработки уже известно количество необходимых пулов соединений и Вам нужно только небольшое количество соединений.
Часто нельзя предугадать заранее количество необходимых пулов соединений. В других случаях это возможно, но это количество недопустимо велико. Например, предположим, что для каждого потребителя, имеющего доступ к Вашему приложению, приложение проверяет пользовательский профиль на предмет определения того, какую информацию из БД вывести. Вы можете дать каждому потребителю уникальный пользовательский идентификатор ID для БД. Такое приложение требует, чтобы каждый пользователь имел свой набор параметров соединений (соответствующий различным пользовательским ID в БД) и, соответственно, разные пулы соединений.
Вы можете создать объект DbPool и соединять и отсоединять его на каждой странице приложения. Это будет работать, только если одно соединение не должно захватывать несколько клиентских запросов. Иначе эта ситуация должна обрабатываться по-разному.
Для данного приложения, вместо создания фиксированного набора пулов соединений на начальной странице приложения или пула на каждой клиентской странице, Вы создаёте одно свойство объекта project, которое будет содержать массив пулов соединений. Доступ к элементам этого массива осуществляется по ключу на базе определённого пользователя.
Во время инициализации Вы создаёте массив, но не помещаете в него элементы (поскольку никто ещё не пытался использовать приложение), как показано здесь:
project.sharedPools = new Object();
Когда пользователь впервые стартует приложение, оно получает идентифицирующий пользователя ключ. На основе этого ключа приложение создаёт объект пула DbPool и сохраняет его в массиве пулов. Имея данный пул соединений, оно может либо соединяться на каждой странице, либо устанавливать соединение так, как описано в разделе Следующий код создаёт пул либо получает уже созданный, проверяет его соединение и работает затем с БД:
// Генерируется уникальный индекс для обращения к данному клиенту, если это // ещё не было сделано на другой странице. О функции ssjs_generateClientID см. // .
if client.id == null { client.id = ssjs_generateClientID(); }
// Если пула для данного клиента ещё нет, он создаётся // и производится его соединение с БД.
project.lock(); if (project.sharedPools[client.id] == null) { project.sharedPools[client.id] = new DbPool ("ORACLE", "myserver", user, password, "", 5, false); } project.unlock();// Для удобства устанавливается переменная для этого пула. var clientPool = project.sharedPools[client.id];// Теперь у Вас есть пул: посмотрим, соединён ли он. Если нет, попытаемся соединить его. // Если это не удаётся, перенаправляем на специальную страницу, // чтобы проинформировать пользователя. project.lock(); if (!clientPool.connected()) { clientPool.connect("ORACLE", "myserver", user, password, "", 5, false); if (!clientPool.connected()) { delete project.sharedPools[client.id]; project.unlock(); redirect("noconnection.htm"); } } project.unlock();// Если Вы дошли до этого места, Вы успешно соединились и // можете работать с БД. clientConn = clientPool.connection(); clientConn.SQLTable("select * from customers"); // ... другие операции с БД ...// Всегда освобождайте соединение, если оно Вам больше не нужно. clientConn.release(); }
Когда пользователь в следующий раз войдёт в приложение (например, с другой страницы приложения), он использует тот же самый код и получит сохранённый пул соединений и (возможно, сохранённый,) объект Connection из объекта project.
Если Вы используете ssjs_generateClientID и сохраняете ID в объекте client, Вам может понадобиться защита от вторжения через доступ к этому ID и, следовательно, к закрытой информации.ПРИМЕЧАНИЕ:
Объект sharedConns, использованный в этом примере кода, не является предопределённым объектом JavaScript. Он просто создан в этом примере и может иметь другое имя по Вашему выбору.
Совместное Использование Объекта project
Для каждого приложения имеется только один объект project. Таким образом, код, исполняемый в любом запросе к данному приложению, может получить доступ к тому же объекту project. Поскольку сервер является многопоточным, могут иметься несколько активных запросов в данный момент времени, либо от одного и того же клиента, либо от разных клиентов.
Для поддержания целостности данных Вы обязаны гарантировать исключительный доступ к свойству объекта project при изменении значения свойства. Неявной блокировки, как это было в предыдущих релизах, больше нет; Вы обязаны запрашивать исключительный доступ. Легче всего сделать это через использование методов lock и unlock объекта project. См. раздел .
Совместное Использование Объекта server
Для всего сервера имеется один объект server. Таким образом, код, выполняемый в любом запросе, в любом приложении, может иметь доступ к одному и тому же объекту server. Поскольку сервер является многопоточным, могут иметься несколько запросов в данный момент времени. Для поддержания целостности данных Вы обязаны гарантировать исключительный доступ к объекту server при внесении изменений.
Также Вы обязаны гарантировать, что имеется исключительный доступ к свойству объекта server, когда изменяется значение этого свойства. Неявной блокировки, как это было в предыдущих релизах, теперь нет; Вы обязаны запрашивать исключительный доступ. Легче всего сделать это через использование методов lock и unlock объекта server. См. раздел .
Создание Базы Данных
Имеются два набора скриптов создания БД для videoapp и oldvideo, находящиеся в соответствующих этим приложениям директориях. Наборы скриптов идентичны. Если Вы запустите один набор, оба приложения смогут использовать БД.
При первом запуске скриптов Вы можете получать ошибки, касающиеся стирания БД или таблиц, которые ещё не существуют. Это нормально; можно спокойно игнорировать эти сообщения.
Создание File-Объекта
Чтобы создать экземпляр класса File, используйте стандартный синтаксис JavaScript для создания объекта:
fileObjectName = new File("path");
Здесь fileObjectName это имя, по которому Вы обращаетесь к файлу, а path это полный путь к файлу. Этот path должен быть в формате серверной файловой системы, а не URL.
Вы можете отобразить имя файла, используя функцию write с File -объектом в качестве аргумента. Например, следующий оператор выводит имя файла:
x = new File("\path\file.txt"); write(x);
Создание Исходных Файлов Приложения
Первым шагом на пути создания приложения JavaScript будет создание и редактирование исходных файлов с кодом. Файл с расширением web для приложения JavaScript может быть исходным файлом одного из двух видов:
Файлом со стандартным HTML или с JavaScript, внедрённым в HTML. Эти файлы имеют расширение .html или .htm.
Файлом только с функциями JavaScript. эти файлы имеют расширение .js.
Если Вы используете JavaScript в HTML-файле, Вы обязаны следовать правилам, указанным в разделе .
Не используйте никаких специальных тэгов в файлах .js; компилятор приложений JavaScript на сервере и интерпретатор JavaScript на стороне клиента считают такие файлы написанными на JavaScript. Поскольку HTML-файл используется и на клиенте, и на сервере, один файл JavaScript обязан использоваться либо на сервере, либо на клиенте; он не может использоваться и там, и там. Следовательно, файл JavaScript может содержать либо клиентский, либо серверный JavaScript, но один файл не может содержать и клиентские, и серверные объекты или функции.
Компилятор приложений JavaScript компилирует и связывает HTML- и JavaScript-файлы, содержащие серверный JavaScript, в единый платформонезависимый байт-код web-файла (имеющего расширение .web), как описано в разделе .
Вы инсталируете web-файл, запускаемый машиной выполнения JavaScript, как описано в разделе .
Создание Курсора
Как только приложение установило соединение с БД, Вы можете создать курсор путём вызова метода cursor ассоциированного объекта database или Connection. Создание объекта Cursor также открывает курсор в БД. Вам не нужно выполнять отдельную команду open.
Можно предоставить следующую информацию при создании объекта Cursor:
Оператор SQL SELECT, поддерживаемый сервером БД. Чтобы гарантировать независимость от вида БД, используйте синтаксис SQL 89/92. Курсор создаётся как виртуальная таблица результата выполнения этого оператора SQL.
Необязательный Булев параметр указывает, является ли курсор обновляемым. Используйте этот параметр только в том случае, когда Вам нужно изменять содержимое БД, как указано в разделе . Не всегда возможно создать обновляемый курсор для каждого оператора SQL, так как это контролируется базой данных. Например, если оператор SELECT будет таким: "select count(*) from videos", Вы не сможете создать обновляемый курсор.
Например, следующий оператор создаёт курсор для записей таблицы CUSTOMER. Записи содержат столбцы id, name и city и упорядочены по значениям столбца id.
custs = connobj.cursor ("select id, name, city from customer order by id");
Этот оператор устанавливает в переменную custs объект Cursor. Запрос SQL может вернуть следующие ряды:
1 Sally Smith Suva 2 Jane Doe Cupertino 3 John Brown Harper's Ferry
Затем Вы можете получить доступ к этой информации через использование методов Cursor-объекта custs. Этот объект имеет свойства id, name и city, соответствующие столбцам виртуальной таблицы.
Когда Вы первоначально создаёте Cursor-объект, указатель позиционируется сразу перед первым рядом виртуальной таблицы. В последующих разделах рассматривается, как получить информацию из виртуальной таблицы.
Вы можете также использовать оператор конкатенации строк (+) и строковые переменные (такие как значения свойств client или request) при конструировании оператора SELECT. Например, следующий вызов использует ранее сохранённый customer ID для последующей специализации запроса:
custs = connobj.cursor ("select * from customer where id = "
+ client.customerID);
При попытке создания Cursor-объекта Вы можете столкнуться с различными проблемами. Например, если оператор SELECT в вызове метода cursor обращается к несуществующей таблице, БД возвращает ошибку, и метод cursor возвращает null вместо Cursor-объекта. В этой ситуации Вы должны использовать методы majorErrorCode и majorErrorMessage для определения возникшей ошибки.
В качестве второго примера, предположим, что оператор SELECT обращается к существующей таблице, в которой нет рядов. В этом случае БД может не возвратить ошибку, а метод cursor возвратит верный Cursor -объект. Однако, поскольку этот объект не содержит рядов, при первой попытке использования метода next в этом объекте он возвратит false. Ваше приложение должно проверять возможность возникновения такой ситуации.
Создание Специального Объекта client
Как уже было сказано ранее, свойства предопределённого объекта client могут иметь только строковые значения. Это ограничение может представлять проблему для работы некоторых приложений. Например, Вашему приложению нужен объект, который существует столько же, сколько предопределённый объект client, но который может принимать в качестве значений свойств объекты или другие типы данных. В этом случае Вы можете создать Ваш собственный объект и сохранить его как свойство объекта client.
В этом разделе приведён пример создания такого объекта. Можете включить этот код как файл JavaScript в Ваше приложение. Затем в начале страницы, на которой нужно использовать этот объект, введите следующий оператор:
var customClient = getCustomClient()
(Разумеется, можно использовать другое имя переменной.) Если это первая страница, запрашивающая данный объект, метод getCustomClient создаёт новый объект. На других страницах он будет возвращать уже существующий объект.
Этот код сохраняет массив всех специальных объектов client, определённых в приложении как значения свойства customClients предопределённого объекта project. Он сохраняет индекс в этом массиве и строковое значение свойства customClientID предопределённого объекта client. Кроме того, этот код использует блокировку/lock, хранимую в свойстве customClientLock объекта project, чтобы гарантировать надёжность доступа к этому массиву. О блокировании см. раздел .
Переменная timeout в функции getCustomClient жёстко кодирует период окончания действия этого объекта. Если Вам нужен другой период окончания действия, специфицируйте другое значение для этой переменной. Независимо от используемого периода действия, Вы должны вызывать метод expiration предопределённого объекта client для установки его срока окончания действия в то же значение, какое специфицировано Вами для специального объекта. О работе этого метода см. раздел .
Для удаления всех закончивших работу специальных объектов приложения вызовите следующую функцию:
expireCustomClients()
Это всё, что нужно сделать! Если Вы используете этот код, предопределённые объекты client и project имеют следующие дополнительные свойства, которые Вы не должны изменять:
client.customClientID
project.customClientsproject.customClientLock
Вы можете специализировать класс путём изменения его методов onInit и onDestroy. Как показано здесь, эти методы - это просто основа. Вы можете добавить код для изменения действий при создании и уничтожении объекта.
Вот этот код:
// Эта функция создаёт новый специальный объект client или запрашивает существующий.
function getCustomClient() { // ==========> Измените жёстко кодированный период ожидания <========== // Примечание: Не забудьте установить окончание обслуживания client-статуса // в то же самое значение, что и использованное ниже в вызове // client.expiration. Это даст возможность индексу отключать все предопределённые // объекты client в то же время, которое содержится в объекте project.
var timeout = 600;
var customClient = null; var deathRow = null;
var newObjectWasCreated = false;
var customClientLock = getCustomClientLock();
customClientLock.lock(); var customClientID = client.customClientID;
if ( customClientID == null ) {
customClient = new CustomClient(timeout);
newObjectWasCreated = true; }
else { var customClients = getCustomClients(); customClient = customClients[customClientID]; if ( customClient == null ) { customClient = new CustomClient(timeout); newObjectWasCreated = true;
} else {
var now = (new Date()).getTime();
if ( customClient.expiration <= now ) {
delete customClients[customClientID];
deathRow = customClient;
customClient = new CustomClient(timeout); newObjectWasCreated = true; }
else { customClient.expiration = (new Date()).getTime() +
timeout*1000;
} }
} if ( newObjectWasCreated ) customClient.onInit(); customClientLock.unlock();
if ( deathRow != null ) deathRow.onDestroy(); return customClient; }
// Функция для удаления старых специальных объектов client. function expireCustomClients()
{ var customClients = getCustomClients();
var now = (new Date()).getTime(); for ( var i in customClients ) {
var clientObj = customClients[i];
if ( clientObj.expiration <= now ) {
var customClientLock = getCustomClientLock();
customClientLock.lock();
if ( clientObj.expiration <= now ) {
delete customClients[i];
}
else {
clientObj = null;
}
customClientLock.unlock()
if ( clientObj != null )
clientObj.onDestroy();
} } }
// Не вызывайте эту функцию явно. // Она используется методами getCustomClient и expireCustomClients. function getCustomClientLock() { if ( project.customClientLock == null ) { project.lock()
if ( project.customClientLock == null )
project.customClientLock = new Lock()
project.unlock() }
return project.customClientLock }
// Не вызывайте эту функцию явно. // Она используется методами getCustomClient и expireCustomClients. function getCustomClients() { if ( project.customClients == null ) { project.lock()
if ( project.customClients == null )
project.customClients = new Object()
project.unlock() }
return project.customClients }
// Конструктор класса CustomClient. Не вызывайте его явно. // Используйте вместо него функцию getCustomClient. function CustomClient(seconds) {
var customClients = getCustomClients();
var customClientID = ssjs_generateClientID();
this.onInit = CustomClientMethod_onInit;
this.onDestroy = CustomClientMethod_onDestroy;
this.expiration = (new Date()).getTime() + seconds*1000;>
client.customClientID = customClientID;
customClients[customClientID] = this; }
// Если нужно специализировать, переопределите следующие две функции.
function CustomClientMethod_onInit() { // ==========> Добавьте код инициализации Вашего объекта <========== // Этот метод вызывается при блокировке. }function CustomClientMethod_onDestroy() {
// ==========> Добавьте код очистки Вашего объекта <==========
// Этот метод не вызывается из блокировки. }
Специальные Замки/Locks для Объектов project и server
Каждый из объектов project и server имеет методы lock и unlock. Вы можете использовать эти методы для получения исключительного доступа к свойствам этих объектов.
В этих методах ничего нового нет. Вам также необходима кооперация с другими участками кода. Вы можете представлять эти методы как имеющие флаги: один флаг с именем "project", а другой - флаг с именем "server." Если другой раздел кода не вызывает project.lock, первый может изменять любые свойства объекта project.
В отличие от метода lock класса Lock, Вы не можете специфицировать таймаут для метода lock объектов project и server. То есть, когда Вы вызываете project.lock, система ожидает бесконечно долго освобождения замка. Если Вы хотите ожидать только в течение определённого периода, используйте экземпляр класса Lock.
В примере использованы методы lock и unlock для получения исключительного доступа к объекту project для модификации свойства ID потребителя:
project.lock()
project.next_id = 1 + project.next_id; client.id = project.next_id; project.unlock();
SQL
Structured Query Language. Стандартный язык для определения, управления и запрашивания реляционных баз данных.
Сравнение Видов Техники Обслуживания Объекта client
Каждый вид техники имеет свои преимущества и недостатки, и то, что является недостатком в одной ситуации, может оказаться преимуществом в другой. Вам необходимо выбрать вид техники, наиболее подходящей для Вашего приложения. Виды техники описаны более детально в последующих разделах; в этом разделе даётся общее сравнение.
В таблице выполнено общее сравнение клиентской и серверной техники.
СервернаяКлиентская
1.
Не ограничивается количество хранимых свойств или занимаемое ими пространство.
Ограничения на свойства.
2.
Занимает дополнительную память сервера в промежутке между клиентскими запросами.
Не использует дополнительную память сервера в промежутке между клиентскими запросами.
Эти различия относительны. Отсутствие ограничения на количество и размер свойств может быть и недостатком, и преимуществом. Вообще нужно ограничивать размер данных приложения, доступных через Internet, чтобы не перегрузить память Вашего сервера. Иначе лучше использовать клиентскую технику. Однако, если у вас приложение для Intranet (внутренней сети), где нужно хранить большой объём данных, можно допустить это на сервере, так как количество клиентов ограничено.
3.
Свойства хранятся в памяти сервера и теряются при рестарте сервера или приложения.
Свойства не хранятся в памяти сервера и не теряются при рестарте сервера.
Если свойства являются настройками пользователя, Вам может понадобиться сохранить их между рестартами сервера; если они относятся к отдельной сессии, может понадобиться, чтобы они были стёрты.
4.
Не увеличивает или незначительно увеличивает сетевой трафик.
Увеличивает сетевой трафик.
Клиентская техника пересылает имя и значение каждого свойства клиенту один или более раз. Это значительно увеличивает сетевой трафик.
Поскольку все серверные виды техники хранят имена и значения свойств на сервере, максимум, что они пересылают клиенту, это сгенерированное имя клиента, используемое при идентификации доступа к структуре данных сервера.
На и на видно, какая информация хранится при использовании каждого вида техники, где она хранится и передаётся ли по сети. На дана информация для клиентской техники.
Рисунок 6.3 Клиентская техника
На дана информация для серверной техники.
Рисунок 6.4 Серверная техника
Имеются некоторые общие для видов (серверной и клиентской) техники вопросы. Для обоих типов техники, использующих куки, браузер обязан поддерживать протокол Netscape cookie protocol. В обоих случаях, когда браузер на клиентской машине закрывается, информация сохраняется в cookie-файле на клиентской машине. В других случаях ограничений нет.
Техника серверных кук создаёт единственную куку для идентификации соответствующего объекта client. В противоположность этому, техника клиентских кук создаёт отдельную куку для каждого свойства объекта client. На технику клиентских кук, следовательно, скорее повлияет ограничение в 20 кук на приложение.
В технике клиентских кук свойства объекта client высылаются клиенту, когда высылается первая часть HTML-страницы. Если Вы изменяете позднее значения свойств объекта client при выполнении действий на странице, эти изменения не отсылаются клиенту и теряются. Это ограничение не действует для другой техники.
Для обеих техник, использующих кодирование в URL, если Ваше приложение конструирует URL на этапе выполнения или использует функцию redirect, необходимо либо вручную присоединять свойства объекта client, которые должны быть сохранены, либо использовать addClient, чтобы машина выполнения присоединила эти свойства. Хотя присоединение свойств не является обязательным для других техник, Вам может понадобиться сделать это, чтобы изменение техники не нарушило работу Вашего приложения.
Кроме того, при использовании техник кодирования URL, как только браузер перейдёт на страницу за пределами приложения или даже отправит форму приложению с использованием метода GET, все свойства объекта client будут утеряны. Свойства не теряются в такой ситуации для других видов техники. Ваш выбор техники частично определяется тем, должны ли существовать свойства объекта client в такой ситуации.
Ваш выбор используемой техники опирается на требования Вашего приложения. Техника клиентских кук не использует дополнительной памяти сервера (как при серверной технике) и высылает информацию только один раз для страницы (в противоположность клиентской технике кодирования URL). Эти факты могут сделать использование техники клиентских кук предпочтительным для больших Internet-приложений. Однако в некоторых случаях другая техника может оказаться более подходящей. Например, серверный IP-адрес работает быстрее, не увеличивая сетевого трафика. Можно использовать это для приложений Вашей Intranet, для которых скорость работы является критичной.
Ссылки на Пакеты и Классы
Простые ссылки на пакеты и классы Java из JavaScript создают объекты JavaPackage и JavaClass. В одном из предыдущих примеров о корпорации Redwood, например, обращение Packages.redwood это JavaPackage -объект. Аналогично обращение java.lang.String это JavaClass -объект.
В большинстве случаев Вам не нужно беспокоиться об объектах JavaPackage и JavaClass: Вы просто работаете с пакетами и классами Java, а LiveConnect прозрачно создаёт эти объекты.
JavaClass -объекты не конвертируются автоматически в экземпляры java.lang.Class при передаче их в качестве параметров Java-методам -- Вы обязаны создать оболочку/wrapper вокруг экземпляра java.lang.Class. В следующем примере метод forName создаёт объект-оболочку theClass, который затем передаётся методу newInstance для создания нового массива.
theClass = java.lang.Class.forName("java.lang.String")
theArray = java.lang.reflect.Array.newInstance(theClass, 5)
Старт Flexi
Вы обязаны стартовать FlexiServer до старта flexi, поскольку стартовая страница flexi пытается соединиться с FlexiServer.
Добавьте $NSHOME\js\samples\flexi в CLASSPATH Вашего web-сервера. О том, как это сделать, см. "Установка LiveConnect".
Используя Application Manager, установите приложение flexi JavaScript, как описано в разделе "Установка Нового Приложения". Параметры, устанавливаемые Вами для flexi, показаны в следующей таблице.
УстановкаЗначение
Nameflexi
Web File Path/Путь к web-файлу$NSHOME\js\samples\flexi\flexi.web
Default Page/Страница по Умолчаниюfsa.html
Initial Page/Начальная Страницаstart.html
Client Object Maintenance/Обслуживание Объекта сlientclient-cookie
Старт FlexiServer
FlexiServer это отдельное приложение Java. Оно может работать только на машине, имеющей JDK 1.0.2. В Enterprise Server 3.01 и в FastTrack Server 3.01 Вы можете также запускать его на машине с JDK 1.1.2. Прежде чем запустить FlexiServer, Вы должны убедиться, что среда работы корректна.
Из оболочки, где Вы запускаете FlexiServer, убедитесь, что Ваша переменная окружения PATH содержит $JDK\bin и что CLASSPATH включает следующее:
... $NSHOME\js\samples\flexi $NSHOME\wai\java\nisb.zip $JDK\lib\classes.zip
Здесь $JDK это директория, в которой установлен JDK, а $NSHOME это директория, в которой установлен Ваш web-сервер.
Если среда корректна, Вы можете стартовать FlexiServer так:
cd $NSHOME\js\samples\flexi\impl java FlexiServer
Вы должны увидеть такое сообщение:
Started FSA Admin: Admin[Server,oid=PersistentId[repId=IDL:Flexi/Admin:1.0,objectName=FSA-Admin]]
С этого момента FlexiServer стартовал как сервис CORBA и зарегистрировал в ORB объект с интерфейсом ::FSA::Admin и именем FSA-Admin. FlexiServer работает в фоновом режиме, ожидая запросов на обслуживание.
Старт, Остановка и Рестарт Приложения
После инсталяции приложения его можно запустить на выполнение. Выберите приложение в списке приложений и щёлкните Start. Если приложение запущено успешно, его статус изменяется со Stopped на Active.
Вы можете запустить приложение, загрузив его URL:
http://server.domain/appmgr/control.html?name=appName&cmd=start
Здесь appName это имя приложения. Вы не можете изменить этот URL, если не имеете привилегий доступа к Application Manager.
Чтобы остановить приложение и сделать его таким образом недоступным для пользователей, выберите имя приложения в списке приложений и щёлкните Stop. Статус приложения изменится на Stopped, и клиенты не смогут запускать его. Вы обязаны остановить приложение, если хотите переместить web-файл или обновить приложение с рабочего сервера на конечном сервере публикаций.
Вы можете также остановить приложение, загрузив следующий URL:
http://server.domain/appmgr/control.html?name=appName&cmd=stop
Здесь appName это имя приложения. Вы не можете изменить этот URL, если не имеете привилегий доступа к Application Manager.
Вы обязаны рестартовать приложение каждый раз после его перестроения/rebuild. Чтобы рестартовать активное приложение, выберите его в списке приложений и щёлкните Restart. Фактически рестарт реинсталирует приложение; программа ищет специфицированный web-файл. Если верного web-файла нет, Application Manager генерирует ошибку.
Вы можете также рестартовать приложение, загрузив следующий URL:
http://server.domain/appmgr/control.html?name=appName&cmd=restart
Здесь appName это имя приложения. Вы не можете изменить этот URL, если не имеете привилегий доступа к Application Manager.
Static-метод или свойство
Метод или свойство встроенного объекта, которые не могут быть свойством экземпляров объекта. Например, Вы можете инстанциировать (создать экземпляры) новые экземпляры объекта Date. Некоторые методы объекта Date, такие как getHours и setDate, являются также методами экземпляров объекта Date. Другие методы объекта Date, такие как parse и UTC, являются static/статическими, и экземпляры объекта Date не имеют этих методов.
Статус-Коды
В следующей таблице дан список статус-кодов, возвращаемых различными методами. Netscape рекомендует не использовать эти значения напрямую. Вместо этого, если метод возвращает ненулевое значение, используйте ассоциированные методы majorErrorCode и majorErrorMessage для определения конкретной ошибки.
Статус-Код
Пояснение
Статус-Код
Пояснение
0
Нет ошибки
14
Null-параметр
1
Недостаточно памяти
15
Объект database не найден
2
Объект не был инициализирован
16
Отсутствует необходимая информация
3
Ошибка конвертации типов
17
Объект не поддерживает несколько читателей
4
БД не зарегистрирована
18
Объект не поддерживает удаление
5
Ошибка, выданная сервером
19
Объект не поддерживает вставку
6
Сообщение сервера
20
Объект не поддерживает обновление
7
Ошибка в библиотеке поставщика
21
Объект не поддерживает обновление
8
Потеря соединения
22
Объект не поддерживает индексы
9
Конец fetch (не смог перевести - прим. перев.)
23
Объект не может быть уничтожен
10
Неверное использование объекта
24
Предоставлено некорректное соединение
11
Столбец не существует
25
Объект не поддерживает привилегии
12
Неверное позиционирование внутри объекта (нарушение границ)
26
Объект не поддерживает курсоры
13
Неподдерживаемая возможность
27
Невозможно открыть
Stopped application/остановленное приложение
Приложение, остановленное Application Manager'ом и недоступное клиентам.
Строка
Если метод возвращает строку, Вы обычно не получаете сообщения об ошибке. Если, однако, метод возвращает null, проверьте ассоциированный error-метод.
Следующие методы возвращают строку:
Connection.majorErrorMessage Connection.minorErrorMessage
Cursor.columnName database.majorErrorMessage database.minorErrorMessage DbPool.majorErrorMessage
DbPool.minorErrorMessage Resultset.columnName
Строковые Значения
Когда Вы передаёте строковые типы JavaScript в качестве параметра Java-методам, Java конвертирует эти значения в соответствии с правилами, описанными в таблице:
Тип Java-параметра
Правила конвертации
lava.lang.String java.lang.Object
Строка JavaScript конвертируется в экземпляр java.lang.String с ASCII-значением.
byte double float int long short
Все значения конвертируются в числа, как описано в .
char
Все значения конвертируются в числа.
boolean
Пустая строка становится false.все другие значения становятся true.
В объекте client отсутствуют значения
В объекте client отсутствуют значения предопределённых свойств, поскольку он предназначен для хранения специфических для приложения данных. Операторы JavaScript могут присваивать специфичные для приложения свойства и значения объекту client. Хорошим примером свойства объекта client является ID-номер потребителя. Когда пользователь в первый раз вызывает приложение, оно обязано присвоить customer ID, как в следующем примере:
client.custID = getNextCustID();
Здесь определяемая в приложении функция getNextCustID используется для вычисления customer ID. Машина выполнения затем присваивает этот ID свойству custID объекта client.
После установки customer ID может оказаться неудобным требовать от пользователя ввода ID на каждой странице приложения. Однако без использования объекта client нет иной возможности ассоциировать корректный customer ID с последующими запросами клиента.
Из-за использования такой техники для обслуживания свойств объекта client при наличии нескольких клиентских запросов имеется одно важное ограничение для значений свойств объекта client. Машина выполнения JavaScript не сервере конвертирует значения всех свойств объекта client в строки.
Не присваивайте объект в качестве значения свойства объекта client. Если Вы это сделаете, машина выполнения конвертирует этот объект в строку; после этого Вы не сможете больше работать с этим объектом. Если значение клиентского свойства представляет другой тип данных, например, number, Вы обязаны конвертировать строковое значение перед тем как его использовать. Например, Вы можете создать целочисленное свойство объекта client:
client.totalNumber = 17;
Затем Вы можете использовать parseInt для инкремента значения totalNumber:
client.totalNumber = parseInt(client.totalNumber) + 1;
Аналогично Вы можете создать Булево свойство объекта client:
client.bool = true;
А затем проверить его:
if (client.bool == "true") write("It's true!"); else
write("It's false!");
У объекта project нет предопределённых
У объекта project нет предопределённых свойств, поскольку он предназначен для содержания специфических для приложений данных, доступных для многих клиентов. Вы можете создавать свойства любого верного типа JavaScript, включая ссылки на другие JavaScript-объекты. Если Вы храните ссылку на другой объект в объекте project, машина выполнения не уничтожает объект, на который ссылаются, по окончании клиентского запроса, в котором объект создаётся. Объект доступен и в течение последующих запросов.
Хороший пример свойства объекта project - следующий доступный ID потребителя. Приложение может использовать это свойство для отслеживания последующих присваиваемых IDs. Любому клиенту, получающему доступ к приложению и не имеющему ID потребителя, присваивается этот ID, и его значение будет увеличиваться для каждого первоначального доступа.
Помните, что объект project существует только в течение периода работы приложения на сервере. Когда приложение останавливается, объект project уничтожается вместе со всеми значениями его свойств. Поэтому, если у Вас имеются данные приложения, которые нужно сохранять постоянно, их необходимо сохранять в БД (см. ) или в файле на сервере (см. ).
Свойства Объекта client как Куки
Если приложение использует технику клиентских кук для работы с объектом client, машина выполнения на сервере сохраняет имена и значения свойств объекта client как куки на клиенте. Об использовании кук для работы с объектом client см. раздел .
Для свойства объекта client propName машина выполнения автоматически создаёт куку с именем NETSCAPE_LIVEWIRE.propName, принимая, что приложение использует технику работы с клиентскими куками. Машина выполнения кодирует значения свойств так, как это требуется по протоколу кук Netscape cookie protocol.
Для доступа к этим кукам в клиентском JavaScript Вы можете извлечь эту информацию путём использования свойства document.cookie и такой функции как getSSCookie, как показано здесь:
function getSSCookie(name) {
var search = "NETSCAPE_LIVEWIRE." + name + "="; var retstr = "";
var offset = 0; var end = 0;
if (document.cookie.length > 0) {
offset = document.cookie.indexOf(search);
if (offset != -1) {
offset += search.length;
end = document.cookie.indexOf(";", offset);
if (end == -1)
end = document.cookie.length;
retstr = unescape(document.cookie.substring(offset, end));
} } return(retstr) }
Функция getSSCookie не является предопределённой функцией JavaScript. Если Вам нужна похожая функциональность, Вы обязаны определить её (функцию) в Вашем приложении.
Чтобы отправленная на сервер информация стала свойством объекта client, добавьте куку с именем, имеющим форму NETSCAPE_LIVEWIRE.propName. Предположим, Ваше приложение использует технику работы с клиентскими куками, а машина выполнения на сервере создаёт свойство объекта client под названием propName для данной куки.
Тогда Вы можете использовать функцию типа следующей:
function setSSCookie (name, value, expire) {
document.cookie =
"NETSCAPE_LIVEWIRE." + name + "="
+ escape(value)
+ ((expire == null) ? "" : ("; expires=" + expire.toGMTString())); }
Здесь функция setSSCookie также не является предопределённой функцией JavaScript. Если Вам необходима аналогичная функциональность, Вы обязаны определить функцию в Вашем приложении.
Вы можете вызывать эти функции в клиентском JavaScript для получения набора значений свойств объекта client, как в следующем примере:
var value = getSSCookie ("answer"); if (value == "") {
var expires = new Date(); expires.setDate(expires.getDate() + 7);
setSSCookie ("answer", "42", Expires); } else
document.write ("The answer is ", value);
Эта группа операторов проверяет, имеется ли свойство объекта client с названием answer. Если нет, код создаёт его и устанавливает значение 42; если найдено, выводится его значение.
В таблице перечислены предопределённые свойства
В таблице перечислены предопределённые свойства объекта request. Некоторые из них соответствуют переменным окружения CGI. Вы можете получить доступ к этим и другим переменным окружения CGI через использование функции ssjs_getCGIVariable, описанной в разделе .
СвойствоОписание
Пример значения agent
Имя и версия клиентского программного обеспечения. Используйте это свойство для адресного применения расширенных возможностей некоторых браузеров.
Mozilla/1.1N (Windows; I; 32bit)
auth_type
Тип авторизации, если запрос защищён авторизацией какого-либо типа. Netscape web-серверы поддерживают базовую авторизацию доступа по HTTP. Соответствует переменной окружения CGI AUTH_TYPE.
basic
auth_user
Имя локального HTTP-пользователя web-браузера, если авторизация доступа HTTP была активирована для данного URL. Заметьте, что это не способ определения имени пользователя, получающего доступ к Вашей программе. Соответствует переменной окружения CGI REMOTE_USER.
vpg
ip
IP-адрес клиента. Может использоваться для авторизации или отслеживания доступа.
198.95.251.30
method
HTTP-метод, ассоциированный с запросом. Приложение может использовать его для определения соответствующего ответа на запрос. Соответствует переменной окружения CGI REQUEST_METHOD.GET
protocol
Уровень протокола HTTP, поддерживаемый клиентским программным обеспечением. Соответствует переменной окружения CGI SERVER_PROTOCOL.
HTTP/1.0
query
Информация из запрашивающей HTML-страницы; это информация в URL, идущая после знака "?". Соответствует переменной окружения CGI QUERY_STRING.
button1=on&button2=off
imageX
Горизонтальная позиция курсора, когда пользователь щёлкает на карте изображений/image map. Описано в разделе .
45
imageY
Вертикальная позиция курсора, когда пользователь щёлкает на карте изображений. Описано в разделе
132uri
Частичный URL запроса: с вырезанными протоколом, именем хоста и, возможно имеющимся, номером порта.
videoapp/add.html
1
Для HTTP 1.0 method имеет одно из значений: GET, POST или HEAD.
Sybase (только для Unix)
На некоторых Unix-платформах Sybase имеет и однопоточный, и многопоточный драйверы. Если Sybase имеет многопоточный драйвер для конкретной Unix-машины, Вы обязаны использовать этот многопоточный драйвер с LiveWire. На этих платформах Ваш web-сервер будет вести себя непредсказуемо с однопоточным драйвером. Это требование применяется как для локальных, так и для удалённых соединений. оно не применяется к Windows-платформам.
См. в список Unix-платформ, на которых Sybase имеет многопоточный драйвер.
Чтобы убедиться в том, что Вы используете многопоточный драйвер, вы обязаны отредактировать Ваш файл $SYBASE/config/libtcl.cfg. Он содержит пару строк, которые включают однопоточный, либо многопоточный драйвер. Вы обязаны иметь одну из этих строк закомментированную, а другую активную. Например, на Solaris найдите эти строки:
[DRIVERS] ;libtli.so=tcp unused ; Это беспоточный tli-драйвер.
libtli_r.so=tcp unused ; Это поточный tli-драйвер.
Удостоверьтесь, что строка для однопоточного драйвера закомментирована, а строка многопоточного драйвера - не закомментирована. Имена файлов различаются на разных платформах, но эти строки всегда расположены в разделе DRIVERS и всегда закомментированы, чтобы различать однопоточный и многопоточный драйверы.
ПРИМЕЧАНИЕ:
Если вы хотите использовать утилиту Sybase isql, Вы обязаны использовать беспоточный tli -драйвер. В этом случае строка для libtli_r.so
обязана быть закомментирована. Об использовании этого драйвера см. документацию по Sybase.
Sybase
Чтобы использовать сервер Sybase, Вы обязаны иметь Netscape Enterprise Server. Вы не можете получить доступ к Sybase из Netscape FastTrack Server.
Если БД и web-сервер находятся на разных машинах, следуйте инструкциям раздела
Если БД и web-сервер находятся на одной машине, следуйте инструкциям раздела
Кроме того, если Вы используете Unix-платформу, и Sybase имеет многопоточный драйвер для этой платформы, следуйте инструкциям раздела См. в список Unix-платформ, на которых Sybase имеет многопоточный драйвер.
Прежде чем использовать нижеуказанные инструкции, Вы обязаны сконфигурировать Ваш Sybase-клиент, как указано в разделе Кроме того, в Unix убедитесь, что переменная окружения PATH содержит $SYBASE\bin и DSQUERY указывает на ваш сервер.
SQL-файлы для создания видео-БД в Sybase, находятся в двух директориях:
$NSHOME\js\samples\videoapp\syb $NSHOME\js\samples\oldvideo\syb
Запустите соответствующий скрипт из командной строки. В Unix это: syb_video.csh userid password
Например:$NSHOME\js\samples\videoapp\syb\syb_load.csh sa
В NT это скрипт:syb_load userid password
Например:c:\netscape\server\js\samples\videoapp\syb\syb_load sa
Можно также запустить скрипт из директории oldvideo.
Теперь можно запускать приложение, сделав изменения, описанные в разделе .
ПРИМЕЧАНИЕ:
Если у Вас на машине установлены и Sybase, и MS SQL Server или DB2, потенциально может возникнуть конфликт имён. Эти производители поставляют утилиты с одинаковыми названиями (bcp и isql). При запуске этих скриптов убедитесь, что переменная окружения настроена для запуска корректной утилиты.
Технология Обслуживания Объекта client
Объект client ассоциирован как с определённым приложением, так и с определённым клиентом. Как было сказано в разделе , машина выполнения создаёт новый объект client всякий раз при поступлении нового запроса от клиента к серверу. Однако целью является сохранение свойств объекта client от одного запроса до следующего. Для этого машине выполнения нужно сохранить свойства объекта client между запросами.
Есть два основных подхода при работе со свойствами объекта client: можно работать с ними на стороне клиента или на сервере. Эти два вида клиентской техники либо сохраняют имена свойств и их значения непосредственно в куках на клиенте, либо в URLs на генерируемой HTML-странице. Все три вида серверной техники сохраняют имена свойств и их значения в структуре данных в памяти сервера, но различаются по используемой для индексирования структуры этих данных схеме.
Вид техники выбирается, когда Вы используете JavaScript Application Manager для инсталяции или модификации приложения, как указано в разделе . Это даёт Вам (или менеджеру сайта) возможность изменять технику обслуживания без перекомпилирования приложения. Однако поведение Вашего приложения может меняться в зависимости от действующей техники обслуживания объекта client, как описано в следующих разделах. Обязательно объясните Вашему менеджеру сайта, от какого вида техники зависит работа Вашего приложения. Иначе менеджер может изменить эти установки и нарушить работу Вашего приложения.
Поскольку некоторые виды этой техники сохраняют информацию в структуре данных на сервере или в куки-файле на клиенте, машина выполнения JavaScript дополнительно должна определять, когда избавиться от этих свойств. В разделе рассматривается, как машина выполнения определяет это, и описываются методы, которые можно использовать для изменения этого поведения.
Тело Запроса
Для нормальных HTML-запросов content type (тип содержимого) запроса будет application/x-www-form-urlencoded. После получения запроса с этим content type машина выполнения JavaScript на сервере обрабатывает запрос, используя данные из тела запроса. В этой ситуации Вы не можете получить прямой доступ к необработанным данным тела запроса. (Конечно, Вы можете получить доступ к его содержимому через объекты request и client, сконструированные машиной выполнения).
Если, однако, запрос имеет любой иной content type, машина выполнения не обрабатывает автоматически тело запроса. В этом случае Ваше приложение должно определить, что делать с содержимым.
Возможно, другая страница Вашего приложения отправила запрос этой странице. Следовательно, Ваше приложение обязано предусматривать возможность получения необычного content type и должно знать, как его обработать.
Для получения доступа к телу запроса Вы используете метод getPostData объекта request. Этот метод принимает в качестве параметра количество символов тела. Если Вы специфицируете 0, тело возвращается целиком. return-значение это строка, содержащая запрошенные символы. Если доступных данных нет, метод возвращает пустую строку.
Можно использовать этот метод для получения всех символов за один раз или читать участки данных. Представляйте тело запроса как поток символов. При чтении Вы можете только продвигаться вперёд; Вы не можете читать одни и те же символы несколько раз.
Чтобы назначить всё тело запроса переменной postData, можно использовать следующий оператор:
postData = request.getPostData(0);
Если в качестве параметра специфицировано 0, метод получает весь запрос. Вы можете точно определить, сколько символов содержится в информации, используя свойство content-length шапки таким образом:
length = parseInt(header["content-length"], 10);
Для получения тела запроса небольшими блоками Вы можете специфицировать иной параметр. Например, следующий код обрабатывает тело запроса блоками по 20 символов:
var length = parseInt(header["content-length"], 10); var i = 0;
while (i < length) { postData = request.getPostData(20);
// ...обработка postData... i = i + 20; }
Конечно, такой подход имеет смысл только тогда, когда Вы знаете, что блоки состоят из 20 символов информации.
Тэг SERVER
Тэг SERVER это наиболее распространённый способ внедрения серверного JavaScript в HTML-страницу. Вы можете использовать тэг SERVER в любой ситуации; обычно, однако, вместо него используются обратные кавычки, если Вы генерируете имена или значения атрибутов для HTML-страницы.
Большая часть операторов между тэгами и не появляется на HTML-странице, высылаемой клиенту. Эти операторы выполняются на сервере. Однако вывод вызовов функции write появляется в результирующем HTML.
Следующая выдержка из приложения Hello World иллюстрирует эти варианты:
This time you are write(request.newname);
client.oldname = request.newname;Enter your name
Получив данный участок кода, машина выполнения генерирует HTML на базе значения request.newname в операторе write. Во втором операторе она просто выполняет операцию JavaScript, присваивая значение request.newname свойству client.oldname. Она не генерирует никакого HTML. Итак, если request.newname будет "Mr. Ed," машина выполнения генерирует из предыдущего отрывка следующий HTML:
This time you are Mr. EdEnter your name
Transaction/транзакция
Группа акций БД, которые выполняются вместе; все акции проходят или все терпят неудачу.
Удаление Приложения
Чтобы удалить приложение, выберите его в списке приложений и щёлкните Remove. Application Manager удалит приложение, и оно больше не сможет быть запущено на сервере. Клиенты не смогут больше получить доступ к приложению. Если Вы удалите приложение, а после этого захотите запустить его, нужно будет инсталировать его заново.
Хотя клиенты потеряют доступ к приложению, удаление его с помощью Application Manager не удаляет физически файлы приложения с сервера. Если Вы хотите полностью удалить файлы, сделайте это вручную.
Удалённый Informix
Только для Unix: Установите Informix ESQL/C Runtime Client 7.22 (называемый также Informix I-Connect), а затем установите следующие переменные окружения:
INFORMIXDIR
Специфицирует верхнюю директорию, в которой установлен Informix.
INFORMIXSERVER
Специфицирует имя Informix-сервера по умолчанию.
INFORMIXSQLHOSTS
Специфицирует путь файла sqlhosts, если Вы поместили его куда-нибудь кроме $INFORMIXDIR/etc/sqlhosts. Эту переменную устанавливать не нужно, если Вы оставили файл sqlhosts в этой директории.
SHLIB_PATH
(HP-UX) Обязана содержать $INFORMIXDIR/lib и $INFORMIXDIR/lib/esql.
Вы обязаны также изменить $INFORMIXDIR/etc/sqlhosts, чтобы оно соответствовал имени службы в файле /etc/services. О том, как это сделать, см. документацию Informix.
Только для NT: Установите Informix ESQL/C Runtime Client 7.20 (называемый также Informix I-Connect.) В процессе установки все необходимые переменные окружения также устанавливаются. Вы используете подходящую утилиту Informix для ввода нужной информации об удалённом сервере, с которым Вы хотите устанавливать соединение.
Если Ваш web-сервер запускается как System, убедитесь, что у вас запущен regcopy.exe.
Все платформы: В зависимости от используемой службы имён, Вам может понадобиться также отредактировать соответствующий файл - добавить IP-адрес удалённой хост-машины, с которой Вы соединяетесь. В NT это файл winnt\system32\drivers\etc\hosts ниже директории NT SystemRoot. На Unix это файл /etc/hosts.
В той же директории добавьте следующую строку к файлу services:
ifmx_srvc port/tcp # Informix Online Server
где ifmx_srvc это имя Вашей службы, а port - номер порта. Номер порта обязан совпадать с номером порта на удалённой машине, который прослушивается Informix-сервером. Чтобы эта строка начала действовать, Вы обязаны либо вставить как минимум один пробел после tcp, либо поместить комментарий в конце этой строки. Например, если Ваша служба Informix называется ifmx1 и номер порта 1321, Вы добавляете следующую строку:
ifmx1 1321/tcp # Informix Online Server
Удалённый Oracle
Только для NT: Вы обязаны установить клиентское программное обеспечение Oracle 7.3.2 для NT. Клиенты Oracle 7.1 и 7.2 не поддерживаются. Вы обязаны также создать файлы конфигурации Oracle, используемые соответствующей утилитой конфигурирования Oracle.
Только для Unix: Прежде чем Вы сможете подключиться к Oracle под Irix, Вы обязаны иметь соответствующие патчи для Irix. См. в информацию о необходимых патчах.
Вы обязаны установить клиентов Oracle 7.3.x для Unix. Клиенты Oracle 7.1 и 7.2 не поддерживаются.
Вы обязаны установить следующие переменные окружения:
ORACLE_HOME
Специфицирует директорию верхнего уровня, в которой установлен Oracle.
TNS_ADMIN
Специфицирует место размещения файлов конфигурации, например, $ORACLE_HOME/network/admin. После инсталяции Oracle создаёт файлы конфигурации под /var/opt/oracle. Если listener.ora и tnsnames.ora находятся в этой директории, Вам может не понадобиться устанавливать TNS_ADMIN, поскольку по умолчанию Oracle использует /var/opt/oracle.
Если эти переменные не установлены надлежащим образом, Oracle возвращает код ошибки ORA-1019 при первой попытке установления соединения. Об обработке ошибок см.
Удалённый Sybase
Только для Unix: Установите следующие переменные окружения:
SYBASE
Директория верхнего уровня, в которой установлен Sybase.LD_LIBRARY_PATH
(DEC) Обязана содержать $SYBASE/lib.
Для Solaris Вы обязаны также следовать инструкциям раздела
Все платформы: Вы обязаны установить SYBASE Open Client/C. Поддерживаемые поставщики перечислены в разделе
Вы можете использовать подходящую утилиту Sybase для ввода в файл sql.ini (NT) и файл interfaces (все платформы) информации об удалённом сервере, с которым Вы хотите установить соединение. Дополнительно см. документацию Sybase.
Уничтожение Объекта client
Приложение может явно уничтожать объект client методом destroy:
client.destroy();
Когда приложение вызывает destroy, JavaScript удаляет все свойства из объекта client. Если Вы используете технику клиентских кук для работы с объектом client, метод destroy уничтожает все значения свойств объекта client, но не влияет на то, что хранится в клиентском cookie-файле. Чтобы удалить и значения свойств из этого cookie-файла, не используйте метод destroy; вместо него используйте expiration с аргументом 0 секунд.
Если Вы используете технику клиентского кодирования URL для работы с объектом client, метод destroy удаляет все свойства объекта client. Ссылки на странице до вызова destroy оставляют свойства объекта client в своих URL, а ссылки, расположенные после вызова метода, не имеют свойств. Поскольку маловероятно, что Вам понадобится, чтобы только некоторые URL страницы содержали свойства объекта client, Вы, вероятно, должны будете вызывать destroy либо вверху, либо внизу страницы, когда используете работу с клиентскими URL. См. также .
Уникальная Ссылка на Объект client
Для некоторых приложений может понадобиться сохранять информацию, специфическую для пары клиент/приложение, в объектах project или server. Два обычных примера - сохранение соединения с БД между клиентскими запросами (описано в ) или хранение специального объекта, имеющего такой же период существования, что и предопределённый объект client, и содержащего значения объектов (описано в разделе ).
В этих случаях Вам необходим способ уникально обратиться к паре клиент/приложение. JavaScript имеет для этого две функции, ssjs_getClientID и ssjs_generateClientID. Они не принимают аргументов; обе возвращают уникальную строку, которую вы можете использовать для идентификации пары.
При каждом вызове ssjs_generateClientID машина выполнения возвращает новый идентификатор. Исходя из этого, если Вы используете эту функцию и Вам нужен идентификатор, существующий дольше, чем отдельный клиентский запрос, Вам нужно сохранить этот идентификатор, возможно, как свойство объекта client. Пример использования этой функции см. в разделе .
Если Вы используете эту функцию и сохраняете ID в объекте client, нужно проявлять осторожность, чтобы хакер не смог получить доступ к этому ID и, как следствие, к закрытой информации.
Альтернативой может стать использование функции ssjs_getClientID. Если Вы применяете одну из этих серверных технологий для объекта client, машина JavaScript генерирует и использует идентификатор для доступа к информации определённой пары клиент/приложение. (О работе с объектом client см. раздел ).
При использовании этих технологий ssjs_getClientID возвращает идентификатор, используемый машиной выполнения. Каждый раз при вызове этой функции из определённой пары клиент/приложение Вы будете получать тот же самый идентификатор. Соответственно, Вам нет необходимости сохранять идентификатор, возвращаемый функцией ssjs_getClientID. Однако, если Вы используете другую технику, эта функция возвращает "undefined"; тогда необходимо использовать функцию ssjs_generateClientID.
Если Вам нужен идентификатор и Вы используете серверную технологию, возможно, понадобится использовать функцию ssjs_getClientID. Тогда Вам не нужно будет самостоятельно сохранять идентификатор и отслеживать его использование; машина выполнения сделает это за Вас. При использовании клиентской техники, однако, Вы не сможете применять функцию ssjs_getClientID; тогда Вы обязаны использовать функцию ssjs_generateClientID.
Updatable cursor/обновляемый курсор
Курсор БД, в котором Вы можете обновлять таблицы на основе содержимого виртуальной таблицы.
Управление Доступом к Приложению
При инсталяции приложения Вам может понадобиться ограничить к нему доступ пользователей, особенно если приложение предоставляет доступ к закрытой информации.
Если Вы работаете на рабочем сервере за брандмауэром/firewall, то можете не беспокоиться об ограничении доступа в процессе разработки приложения. Удобно не иметь ограничений доступа в процессе разработки приложения, так как Вы можете быть уверены в защищённости приложения от атак за стеной firewall. Если Вы используете учебные данные на стадии разработки, то риск ещё меньше. Однако, если Вы публикуете Ваше приложение, Вы должны быть уверены, что любой посетитель Вашего приложения может им пользоваться.
Если Вы закончили разработку и готовы опубликовать приложение, необходимо предусмотреть его защиту. Вы можете ограничить доступ, применив к приложению стиль конфигурации сервера. О стилях конфигурации см. руководство администратора Вашего web-сервера.
URL Приложения
При установке приложения Вы обязаны задать ему имя. Это имя определяет базовый URL
приложения: тот URL, который клиенты используют для доступа к странице по умолчанию данного приложения JavaScript.
Базовый URL приложения имеет форму:
http://server.domain/appName
Здесь server это имя HTTP-сервера, domain это домен Internet (включая субдомены), а appName это имя приложения, которое Вы ему дали при инсталяции. Отдельные страницы приложения достигаются через URL приложения в форме:
http://server.domain/appName/page.html
Здесь page это имя страницы приложения. Например, если Ваш сервер называется coyote, а домен имеет имя royalairways.com, базовый URL для приложения hangman будет:
http://coyote.royalairways.com/hangman
Если клиент запрашивает этот URL, сервер генерирует HTML для страницы по умолчанию приложения и высылает её клиенту. URL приложения страницы winning в этом приложении:
http://coyote.royalairways.com/hangman/youwon.html
Важно!
Прежде чем инсталировать приложение, убедитесь, что выбранное Вами имя приложения не присвоило существующий URL на Вашем сервере. Машина выполнения JavaScript направляет все клиентские запросы по URL, соответствующим URL приложения, в директорию, специфицированную для web-файла. Таким образом можно "обмануть" нормальную корневую директорию.
Например, предположим, клиент запрашивает URL, который начинается с префикса из предыдущего примера:
http://coyote.royalairways.com/hangman
В этом случае машина выполнения на сервере ищет документ в директории samples\hangman, а не в нормальной корневой директории сервера. Сервер обслуживает в этой директории страницы, которые не компилируются в приложение.
Вы можете поместить Ваши исходные (неоткомпилированные) файлы серверного JavaScript в ту же директорию, что и web-файл; однако Вы должны делать это только для отладки. Если Вы публикуете Ваше приложение для общего пользования, Вы, по соображениям безопасности, не должны публиковать неоткомпилированные файлы серверного JavaScript.
URL
Universal Resource Locator. Схема адресации, используемая в World Wide Web.
Установка flexi как CORBA-Клиента
Файл start.html это начальная страница приложения JavaScript flexi. Эта страница использует LiveConnect для инициализации ISB for Java и установления соединения с FSA-Admin.
// Инициализируется orb.
project.orb = Packages.org.omg.CORBA.ORB.init();// Устанавливается соединение с сервисом "FSA-Admin". // По умолчанию принимается, что name service запущен на текущем сервере.
nameHost = "http://" + server.hostname; serviceName = "/FSA-Admin";
serviceURL = nameHost + serviceName;// Разрешается имя и получается ссылка на стаб Admin. project.fsa_admin = Packages.Flexi.AdminHelper.narrow(
netscape.WAI.Naming.resolve(serviceURL));
Первый оператор инициализирует ISB for Java, вызывая static-метод init Java-класса org.omg.CORBA.ORB. Он сохраняет возвращённый объект как свойство объекта project, так что он доступен для всего приложения.
Второй набор операторов определяет URL, который использовался для регистрации объекта FSA-Admin. Если Вы использовали при регистрации этого объекта другой URL (как описано в последнем разделе), Вам нужно сделать соответствующие изменения в этих операторах. URL, используемый в CORBA-сервере, обязан быть точно тем же, что и URL, используемый в CORBA-клиенте.
Код затем вызывает метод resolve объекта netscape.WAI.Naming для установления соединения с объектом Admin, который был зарегистрирован FlexiServer как FSA-Admin. Наконец, он вызывает метод narrow объекта AdminHelper для приведения полученного объекта к соответствующему типу Java-объекта. Этот Java-метод возвращает Java-объект, соответствующий распределённому объекту. Машина выполнения JavaScript обёртывает этот Java-объект как JavaScript-объект и сохраняет его как свойство объекта project. Теперь Вы можете вызывать методы и получать доступ к свойствам этого возвращённого объекта, как и любого другого Java-объекта. Другие страницы flexi работают через этот объект.
И ещё раз - о том, как работают CORBA-объекты, см. книгу .
Установка FlexiServer как CORBA-Сервера
Функция main отдельного Java-приложения реализована в flexi\impl\FlexiServer.java. Его код таков:
import org.omg.CORBA.*;class FlexiServer { public static void main(String[] args) {
try { // Инициализируются orb и boa.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
org.omg.CORBA.BOA boa = orb.BOA_init();
// Создаётся серверный объект. Admin __admin = new Admin(); // Информирует boa, что серверный объект готов. boa.obj_is_ready(__admin); // Регистрируется имя объекта с именем сервиса. // Сначала определяется хост имени сервиса, по умолчанию это :80. String _nameServiceHost = null; if (args.length > 0) { // Принимается, что первый arg это имя хоста имени // сервиса. Ожидаемый формат: : _nameServiceHost = args[0]; }
else { String _localHostName = null; try { _localHostName= java.net.InetAddress.getLocalHost().getHostName(); _nameServiceHost = _localHostName + ":80"; } catch (java.net.UnknownHostException e) { System.out.println("Couldn't determine local host; can't register name."); } } String _regURL = "http://" + _nameServiceHost + "/FSA-Admin"; System.out.println("Registering Admin object at URL: " + _regURL); // Регистрируется серверный объект.
netscape.WAI.Naming.register(_regURL, __admin);
System.out.println("Started FSA Admin: " + __admin); boa.impl_is_ready();
} catch (org.omg.CORBA.SystemException e) { System.err.println(e); }
} }
Этот код инициализирует ORB и создаёт экземпляр класса Admin. Затем экземпляр регистрируется как распределённый объект с URL в форме http://host
:port/FSA-Admin. По умолчанию host это имя хоста, на котором запущен FlexiServer, а port равен 80. Вы можете поставить Ваши собственные значения для host:port путём передачи их как аргументов для FlexiServer при его старте. Чтобы использовать локальный хост, но другой номер порта, Вам нужно изменить исходный код и перекомпилировать его. Если код имеет соответствующее имя, он регистрирует объект, используя метод register объекта netscape.WAI.Naming. Дополнительно см. книгу .
Наконец, код печатает сообщение на консоль и ожидает запросы от CORBA-клиентов. В данном случае единственным CORBA-клиентом, который знает о нём, является приложения flexi на языке JavaScript.
Установка Нового Приложения
Вы не можете запустить приложение, и клиенты не могут получить к нему доступ, пока Вы не установите его. Инсталяция приложения идентифицирует его на сервере. После установки Вы можете перестроить/rebuild и запустить приложение любое число раз. Приложение нужно переустановить только тогда, когда Вы его удалили. Вы можете установить до 120 приложений JavaScript на один сервер.
Прежде чем устанавливать, Вы обязаны поместить все файлы, имеющие отношение к приложению, в соответствующую директорию путём публикации файлов. Иначе Вы получите сообщение об ошибке при попытке инсталяции. Из соображений безопасности, Вы можете не захотеть публиковать свои исходные файлы JavaScript на сервер публикации. См. в разделе об ограничениях на размещение файлов.
Чтобы установить новое приложение с помощью Application Manager, щёлкните Add Application. В ответ Application Manager выведет в правом фрэйме форму, показанную на . (Цветовая схема в Enterprise Server 4.0 будет другой).
Рисунок 3.4 Форма Add Application
Заполните поля в форме Add Application следующим образом:
Name: имя приложения. Это имя идентифицирует URL приложения. Например, имя приложения Hello World это "world," а URL приложения - это http://server.domain/world. Это необходимое поле, и имя, которое Вы запишете, обязано отличаться от имён других приложений на данном сервере. См. .
Web File Path: полное путево́е имя web-файла приложения. Это поле необходимо. Например, если сервер Netscape установлен в директории c:\nshome, путь web-файла для приложения Hello World будет
Default Page: страница по умолчанию, которая загружается машиной выполнения JavaScript, если пользователь не специфицировал конкретную страницу в URL. Эта страница аналогична index.html для стандартного URL.
Initial Page: начальная страница, которая выполняется машиной выполнения JavaScript, когда Вы запускаете приложение в Application Manager. Эта страница выполняется точно один раз при запуске приложения. Она обычно используется для инициализации значений, создания блокировок/locks и установления соединения с БД. Любой исходный JavaScript на этой странице не может использовать предопределённые объекты request или client. Это необязательное поле.
Built- in Maximum Database Connections: значение по умолчанию - максимальное количество соединений с БД, которое может иметься в данном приложении в один момент времени через использование предопределённого объекта database. Код JavaScript может переопределить это значение путём вызова метода database.connect.
External Libraries: пути к внешним библиотекам, используемым в приложении. Если Вы специфицируете несколько библиотек, разделите имена запятыми или точкой с запятой. Это поле по выбору/optional. Библиотеки, установленные для одного приложения, могут использоваться всеми приложениями на данном сервере. См. .
Client Object Maintenance: техника, используемая для сохранения свойств объекта client. Это может быть клиентская "кука"/cookie, URL клиента, IP сервера, серверная кука или URL сервера. См. .
После того как Вы предоставили всю требуемую информацию, нажмите Enter для инсталяции приложения, Reset для очистки всех полей или Cancel для отмены операции.
Вы обязаны остановить и рестартовать сервер после добавления или изменения внешних библиотек. Вы можете рестартовать сервер из Server Manager; см. руководство администратора сервера.
Установки для LiveConnect
Чтобы использовать Java-классы в LiveConnect, Вам нужно установить CLASSPATH сервера. Полное описание этой процедуры дано в и в .
Версии JavaScript
Каждая версия Netscape Enterprise Server поддерживает свою версию JavaScript. Чтобы помочь Вам при создании скриптов, совместимых с несколькими версиями Enterprise Server, в этом учебнике используются сокращённые обозначения версий сервера, в которых каждая возможность реализована.
Версия JavaScriptВерсии Enterprise Server
JavaScript 1.2
Netscape Enterprise Server 3.6 (NES 3.6)
JavaScript 1.4
Netscape Enterprise Server 4.0 (NES 4.0)
Visigenic ODBC-Драйвер (только Unix)
При установке сервера он запускается как пользователь: root, nobody или определённый пользователь сервера. Выбранный вами пользователь должен иметь существующую домашнюю директорию, которую, возможно, понадобится создать. Например, домашняя директория по умолчанию для пользователя nobody в системе Irix это /dev/null. Если Вы устанавливаете Ваш сервер в Irix как nobody, Вы обязаны дать пользователю nobody другую домашнюю директорию.
В этой домашней директории обязан находиться файл .odbc.ini. Например, если Вы запускаете сервер как root, этот файл находится в корневой директории (/).
Установите следующие переменные окружения:
LD_LIBRARY_PATH
(Solaris и Irix) Добавьте местонахождение ODBC-библиотек в данную переменную. В предыдущем примере это может быть /u/my-user/odbcsdk/lib.
SHLIB_PATH
(HP-UX) Добавьте местонахождение ODBC-библиотек в данную переменную.
LIBPATH
(AIX) Добавьте местонахождение ODBC-библиотек в данную переменную.
ПРИМЕЧАНИЕ:
Visigenic больше не обновляет свои существующие ODBC--драйверы и SDK. Вместо этого Visigenic избрал INTERSOLV для предоставления обновлённого пути для этих драйверов и продуктов. (См. ). Visigenic будет предоставлять документ, проясняющий операционные различия между ODBC-драйверами Visigenic и INTERSOLV.
Visual JavaScript
Netscape Visual JavaScript это утилита визуальной разработки на базе компонентов для платформы Netscape Open Network Environment (ONE). Он первоначально предназначался для использования разработчиками межплатформенных стандартизованных web-приложений из готовых компонентов с минимальными затратами на программирование. Эти приложения базируются на HTML, JavaScript и Java.
О Visual JavaScript см.
.
Внедрение JavaScript в HTML
Есть два способа встроить операторы серверного JavaScript в HTML-страницу:
Тэгом SERVER.
Используйте этот тэг для размещения в нём одиночного оператора JavaScript или нескольких операторов. Оператор расположен между тэгами и . Вы можете перемежать тэги SERVER полными операторами HTML. Никогда не помещайте тэг SERVER между открывающей (<) и закрывающей (>) угловыми скобками тэга HTML. (См. ). Также не используйте тэг