Серверный JavaScript 1.4. Руководство по использованию

Active application/активное приложение

Приложение JavaScript, которое стартовало и работает, или к которому клиенты осуществляют доступ.

Альтернативные Публикации

Имеются две альтернативы для публикации распределённых CORBA-объектов, представляющие интерес при работе с серверным JavaScript:
Объект может быть создан web-сервером (а не приложением JavaScript) и запущен на web-сервере.

  • Объект может быть создан приложением JavaScript и запущен на web-сервере.

  • В этих альтернативных вариантах CORBA-клиент и CORBA-сервер оба работают в одном процессе web-сервера.
    С этой точки зрения, если CORBA-клиент не является приложением JavaScript, первый вариант пригоден для тех же целей, что и в случае, когда CORBA-сервер запущен как отдельный процесс.
    Однако второй вариант, создающий распределённый объект в приложении JavaScript, реально делает это приложение сервисом CORBA. иллюстрирует эти альтернативы.
    Рисунок 22.3 Приложение JavaScript как CORBA-сервер

    Альтернативные Публикации
    Ещё раз: среды выполнения Java и JavaScript находятся вместе на одном web-сервере. Они взаимодействуют через использование LiveConnect стандартным способом, описанным ранее в этой главе. В это случае, однако, процессы Java и JavaScript действуют вместе как CORBA-сервис. Этот сервис затем взаимодействует с CORBA-клинтом через ISB for Java стандартным способом. Образец-приложение bank это пример приложения JavaScript, реализующего CORBA-сервис.
    В данном случае CORBA-клиент может находиться на любой машине, имеющей ORB с IIOP, и может быть написан на любом языке. Интересно то, что CORBA-клиент может быть клиентским приложением Java (и через LiveConnect на клиенте - клиентским приложением JavaScript). Это даёт совершенно другой способ взаимодействия клиентского приложения JavaScript с серверным приложением JavaScript.

    Application URL/URL приложения

    Страница в приложении JavaScript, являющаяся базовым URL приложения. Клиенты используют URL приложения для доступа к конкретным страницам приложения.

    Аргументы Типа char

    Вы не можете передать односимвольную строку Java-методу, требующему аргумента типа char. Вы обязаны передать таким методам целое число, соответствующее значению Unicode для данного символа. Например, следующий код присваивает значение "H" переменной c:
    c = new java.lang.Character(72)

    Архитектура Приложений JavaScript

    Как уже говорилось, приложения JavaScript имею части, работающие на стороне клиента и на сервере. Кроме того, многие приложения JavaScript используют LiveWire Database Service для соединения приложения с реляционной базой данных. Исходя из этого, Вы можете представить приложения JavaScript как имеющие трёхслойную клиент-серверную архитектуру, как показано на .
    Рисунок 2.1Архитектура среды клиент-серверного приложения на языке JavaScript

    Архитектура Приложений JavaScript
    Три слоя - это:
    WWW-клиенты (такие как Netscape Navigator-клиенты): Этот слой предоставляет приложению межплатформенный интерфейс конечного пользователя. Этот слой может также содержать некоторую логику приложения, такую как правила проверки данных, реализованные в клиентском JavaScript. Клиенты могут находиться внутри или за пределами прокси-сервера корпоративной сети.

  • Netscape WWW-сервер/БД клиент: Этот слой состоит из Netscape-сервера с включённым JavaScript. Он содержит логику приложения, обслуживает безопасность и контролирует доступ к приложению нескольких пользователей, используя серверный JavaScript. Этот слой позволяет клиентам как в пределах действия, так и за пределами прокси-сервера иметь доступ к приложению. WWW -сервер также работает как клиент с любым установленным сервером БД.

  • Серверы баз данных: Этот слой состоит из SQL-серверов БД, работающих обычно на высокопроизводительных рабочих станциях. Он содержит все данные БД, метаданные и правила ссылочной целостности/referential integrity, необходимые для работы приложения. Этот слой обычно находится в зоне действия прокси-сервера корпоративной сети и может предоставлять слой безопасности дополнительно к слою безопасности WWW -сервера. Netscape Enterprise Server поддерживает использование серверов БД: ODBC, DB2, Informix, Oracle и Sybase. Netscape FastTrack Server поддерживает только ODBC. Дополнительно о LiveWire Database Service см.

  • Клиентская среда JavaScript работает как часть WWW -клиентов, а серверная среда JavaScript работает как часть Netscape web-сервера с доступом к одному или более серверов БД. показывает более детально, как серверная среда JavaScript и приложения, созданные для неё, встраиваются в Netscape web-сервер.

    Верхняя часть демонстрирует то, как серверный JavaScript встраивается в Netscape web-сервер. Внутри web-сервера среда работы серверного JavaScript состоит из трёх основных компонентов, перечисленных ниже. JavaScript Application Manager работает поверх серверного JavaScript, как это делается в образце приложения, предоставленном Netscape (таком как приложение videoapp), и в любом приложении, созданном Вами.



    Рисунок 2.2 Серверный JavaScript в среде Netscape-сервера


    Архитектура Приложений JavaScript

    Имеются три главных компонента среды работы JavaScript:

  • Библиотека времени выполнения JavaScript: этот компонент предоставляет базовую функциональность JavaScript. Примером может служить Session Management Service, которая предоставляет предопределённые объекты для помощи в обслуживании Вашего приложения и совместного использования информации клиентом и сервером и несколькими приложениями. Служба Session Management Service описана в .


  • Библиотека LiveWire доступа к БД: Этот компонент расширяет базовую функциональность серверного JavaScript классами и объектами, которые предоставляют аналогичный доступ к внешним серверам БД. Это описано в


  • Виртуальная машина Java (ВМ): В отличие от других компонентов, ВМ Java используется не только в JavaScript; любое Java-приложение, запущенное на сервере, использует эту ВМ. ВМ Java была доработана для того, чтобы дать приложениям JavaScript возможность получать доступ к Java-классам через использование LiveConnect -функциональности JavaScript. LiveConnect описана в


  • В целом приложение на JavaScript может содержать операторы, интерпретируемые клиентом (интерпретатором JavaScript, предоставляемым Netscape Navigator'ом или некоторыми другими web-браузерами) и сервером (машиной выполнения JavaScript, уже рассмотренной).

    Когда вы запускаете приложение JavaScript, происходят различные действия: некоторые на сервере, и некоторые - на клиенте. Хотя конечному пользователю не обязательно знать все детали, Вам как разработчику приложения необходимо понимать, что происходит "под капотом."


    При создании приложения Вы пишете HTML-страницы, которые могут содержать операторы серверного и клиентского JavaScript. В исходном коде HTML клиентский JavaScript находится в тэгах SCRIPT, а серверный JavaScript - в тэгах SERVER.

    Вы можете также писать файлы, содержащие только операторы JavaScript без тэгов HTML. Такой JavaScript-файл может содержать либо клиентский, либо серверный JavaScript; один файл не может содержать и клиентские, и серверные объекты или функции.

    JavaScript VM (Виртуальная Машина), используемая в Netscape Enterprise Server 4.0, реализует значительные улучшения для обработки локальных переменных (то есть переменных, которые объявлены внутри функции), по сравнению с NES 3.6. Соответственно, рекомендуется минимизировать использование глобальных переменных (переменных между тэгами и ) и переписать приложения для использования функций там, где это возможно. Это значительно повысит производительность приложения.

    Если файлы HTML и JavaScript содержат серверный JavaScript, Вы затем компилируете их в единый исполняемый файл приложения JavaScript. Этот файл называется web-файлом и имеет расширение .web. Компилятор приложений JavaScript развёртывает HTML-код в платформонезависимые байт-коды, разбирая и компилируя операторы серверного JavaScript.

    Наконец, Вы публикуете Ваше приложение на Вашем web-сервере и используете JavaScript Application Manager для инсталяции и запуска приложения, чтобы пользователи могли получить к нему доступ.

    На этапе прогона, когда клиент запрашивает страницу приложения серверного JavaScript, машина выполнения локализует представление этого файла в web-файле приложения. Она запускает весь найденный серверный код и создаёт HTML-страницу для отправки клиенту. Эта страница может содержать как обычные тэги HTML, так и операторы клиентского JavaScript. Весь серверный код запускается на сервере до отправки страницы клиенту и до выполнения любого HTML или клиентского JavaScript. Соответственно, Ваш серверный код не может использовать клиентские объекты, так же как и клиентский код не может использовать серверные объекты.

    Дополнительно см.

    Архитектура Приложения

    Этот раздел ориентирует Вас на реализацию некоторой функциональности в videoapp. Он описывает, как приложение работает с БД и детали процедуры аренды видео. Другие задачи похожи.

    ASCII

    American Standard Code for Information Interchange. Определяет коды, используемые для хранения символов в компьютерах.

    Автоматическое Отображение Результатов Выполнения Запроса

    Наиболее простым и быстрым способом отобразить результаты выполнения запросов к БД является использование метода SQLTable объекта database или объекта Connection. Метод SQLTable принимает оператор SQL SELECT и возвращает HTML-таблицу. Каждый ряд и столбец в запросе это ряд и столбец таблицы. Таблица HTML имеет также заголовочную ячейку для каждого столбца таблицы БД.
    Метод SQLTable не даёт Вам возможности управлять форматированием вывода. Кроме того, если вывод содержит объект Blob, этот объект не выводится как изображение. (Об использовании blob см. раздел ). если Вы хотите специализировать вывод, используйте курсор БД для создания Вашей собственной функции вывода/отображения. См. также .
    В качестве примера: если myconn это Connection -объект, следующий оператор JavaScript отображает результат выполнения запроса к БД в виде таблицы:
    myconn.SQLTable("select * from videos");
    Вот первая часть таблицы, которая могла бы быть сгенерирована этим оператором:

    TitleID Year
    CategoryQuantity On Hand
    Synopsis

    A Clockwork Orange

    1

    1975

    Science Fiction

    5

    3

    Little Alex and his droogies stop by the Miloko bar for a refreshing libation before a wild night on the town.

    Philadelphia Story

    1

    1940

    Romantic Comedy



    Katherine Hepburn and Cary Grant are reunited on the eve of her remarriage, with Jimmy Stewart for complications.


    Base application URL/базовый URL приложения

    Имя приложения JavaScript, как оно специфицировано в Application Manager'е. Клиенты используют application URL для доступа к странице по умолчанию данного приложения.

    Безопасное Совместное Использование Объектов с Блокировкой/Locking

    Рабочая среда для версии 3.x или 4.x Netscape-сервера является многопоточной; то есть она обрабатывает более одного запроса в единицу времени. Поскольку эти запросы могут требовать выполнения JavaScript, то более чем один поток выполнения JavaScript может быть активным в одно и то же время.
    Если несколько потоков одновременно пытаются изменить свойство одного и того же объекта JavaScript, они могут привести этот объект в несоответствующее состояние. Участок кода, в котором необходимо выполнять один, и только один, поток выполнения в единицу времени, называется критическим разделом/сritical section.
    Один объект server используется совместно всеми клиентами и всеми приложениями, работающими на сервере. Один объект project используется всеми клиентами, получающими доступ к одному приложению на сервере. Кроме того, Ваше приложение может создавать другие объекты, которые оно предоставляет в совместное пользование клиентским запросам, или оно даже может
    совместно с другими приложениями использовать объекты. Для поддержания целостности данных в этих совместно используемых объектах Вы обязаны получить исключительный доступ к объекту, прежде чем изменять любое его свойство.
    Важно!
    В отличие от предыдущих релизов, неявная блокировка объектов project и server теперь отсутствует.
    Чтобы лучше понять, что происходит, рассмотрим следующий пример. Предположим, Вы создаёте совместно используемый объект project.orders для отслеживания заказов пользователей. Вы обновляете project.orders.count каждый раз при получении нового заказа, используя следующий код:
    var x = project.orders.count;
    x = x + 1;
    project.orders.count = x;
    Предположим, что project.orders.count первоначально установлено в 1 и что поступили два новых заказа в двух разных потоках. Произойдёт следующее:
    Первый поток сохраняет project.orders.count в переменной x.

  • Прежде чем продолжить, второй поток запускается и сохраняет то же самое значение в своей копии переменной x.

  • С этого момента оба потока имеют значение 1 в x.

  • Второй поток завершает своё выполнение и устанавливает project.orders.count в 2.
  • Первый поток продолжает выполнение, не зная, что значение project.orders.count изменилось, и также устанавливает 2 в х.

  • Итак, конечное значение project.orders.count будет 2, хотя корректным должно быть 3.
    Чтобы избежать проблем такого рода, Вам нужно получить исключительный доступ к свойствам совместно используемых объектов перед тем как записывать в них. Для этих целей Вы можете конструировать Ваши собственные экземпляры класса Lock, работающие с любым совместно используемым объектом. Кроме того, объекты server и project имеют методы lock и unlock, которые Вы можете использовать для ограничения доступа к этим объектам.

    BLOb

    Binary large object/двоичный большой объект. Формат двоичных данных, хранимых в реляционной базе данных.

    Блокировка Файлов

    Часто доступ ко многим приложениям могут выполнять одновременно многие пользователи. Вообще разные пользователи не должны пытаться одновременно вносить изменения в файлы, поскольку это может привести к непредсказуемым ошибкам.
    Чтобы предотвратить модификацию файла одновременно несколькими пользователями, используйте один из механизмов блокирования, предоставляемых службой Session Management Service, как описано в разделе . Если один пользователь блокировал файл, другие пользователи приложения должны ждать, пока файл не будет разблокирован. В общем это означает, что lock (замок/блокировка) должна предшествовать всем файловым операциям; после выполнения операций должно выполняться unlock (разблокирование).
    Если только одно приложение может модифицировать данный файл, Вы можете получать блокировку в объекте project. Если более чем одно приложение может иметь доступ к одному и тому же файлу, получайте блокировку в объекте server.
    Например, у Вас создан файл myFile. Затем Вы может использовать его так:
    if ( project.lock() ) {
    myFile.open("r");

    // ... файл используется ...

    myFile.close();

    project.unlock();
    }
    Таким образом, только один пользователь приложения может изменять файл в данный момент времени. Для более тонкого управления блокировкой Вы можете создать Ваш собственный экземпляр класса Lock для управления доступом к данному файлу. Это описано в разделе .

    Булево Значение

    Следующие методы возвращают Булевы значения:
    Connection.connected
    Cursor.next
    database.connected
    DbPool.connected

    Resultset.next
    Если метод возвращает Boolean-значение, true обычно указывает на успешное выполнение, в то время как false указывает на некоторое другое состояние. Return-значение false не означает реальной ошибки; оно может означать и условие успешного завершения.
    Например, Connection.connected возвращает false для указания на то, что Connection -объект в данное время не соединён. Это может означать, что ошибка возникла при создании Connection -объекта или что ранее использованное соединение было намеренно разорвано. Эти события не являются ошибками метода connected. Если ошибка возникла при создании объекта, Ваш код должен отлавливать ошибку в работе этого метода. Если соединение было разорвано, Вы можете установить его вновь.
    Второй пример - Cursor.next возвращает false, когда Вы ряды курсора закончились. Если оператор SELECT, используемый для создания Cursor -объекта, находит таблицу, но не находит столбцы, соответствующие условию оператора SELECT, создаётся пустой курсор. При первой Вашей попытке вызова метода next для этого курсора он возвращает false. Ваш код должен учитывать такую возможность.

    Булевы Значения

    Когда Вы передаёте Булев тип JavaScript в качестве параметра Java-методам, Java конвертирует эти значения в соответствии с правилами, описанными в таблице:
    Тип Java-параметраПравила конвертации

    boolean

    Все значения конвертируются непосредственно в Java-эквиваленты.

    lava.lang.Boolean
    java.lang.Object

    Создаётся новый экземпляр java.lang.Boolean. Каждый параметр создаёт новый экземпляр, а не экземпляр с тем же примитивным значением.

    java.lang.String

    Значения конвертируются в строки. Например:
    true становится "true"
  • false становится "false"

  • byte
    char
    double
    float
    int
    long
    short

  • true становится 1
  • false становится 0

  • Когда JavaScript Boolean передаётся в качестве параметра Java-методу, ожидающему экземпляр java.lang.String, Boolean конвертируется в строку. Используйте операцию == для сравнения результата конвертации с другими строковыми значениями.

    Bytecodes/байт-коды

    Платформонезависимый код объекта, посредник между исходным кодом и специфическим для платформы машинным кодом.

    CGI

    Common Gateway Interface. Спецификация для сообщения между HTTP-сервером и программами-шлюзами на сервере. CGI это популярный интерфейс, используемый для создания серверных web-приложений на языках типа Perl или C.

    Часть 1Разработка Серверных Приложений

    В этой главе дан обзор типичного приложения, написанного на серверном JavaScript, и показано, как настроить систему для разработки серверных приложений.
    В этой главе описан процесс разработки Вашего приложения: как использовать компилятор приложений JavaScript и менеждер Application Manager серверов Netscape для установки или отладки Вашего приложения. Об использовании только клиентского JavaScript см. книгу
    Клиентский JavaScript. Руководство.

    Часть 2Возможности Серверного JavaScript


    В главе рассматривается пример приложения серверного JavaScript, поставляемого вместе с Netscape web-серверами. Это введение в использование серверного JavaScript при помощи двух простых приложений-образцов.
    В этой главе даны основы серверного JavaScript, серверной функциональности и различий между клиентским и серверным JavaScript. Описано, как внедрить серверный JavaScript в HTML-файлы. Рассмотрено, что происходит во время прогона программы на клиенте и на сервере и как использовать JavaScript для изменения HTML-страницы, отправляемой клиенту, и, наконец, как совместно использовать информацию в клиентских и серверных процессах.

    В этой главе рассмотрены объекты службы Session Management Service, введённые в серверном JavaScript для обеспечения возможности совместного использования данных несколькими клиентскими запросами к приложению, несколькими пользователями к одному приложению или даже несколькими приложениями на сервере.
    В этой главе описана дополнительная функциональность серверного JavaScript, которую вы можете использовать для отправки сообщений e-mail из Вашего приложения, доступа к файловой системе сервера, подключения в приложение внешних библиотек или прямого манипулирования клиентскими запросами и ответами клиенту.
    Дата последнего обновления: 29 сентября 1999 г.
    © Copyright © 1999 Sun Microsystems, Inc. Некоторая часть Copyright © 1999 Netscape Communications Corp. Все Права Зарезервированы.

    Часть 3Служба LiveWire Database Service


    В главе обсуждается, как использовать LiveWire Database Service для соединения приложения с реляционными БД DB2, Informix, ODBC, Oracle и Sybase и как выбрать наилучшую методологию соединения с БД.

    В главе обсуждается работа с реляционными БД DB2, Informix, ODBC, Oracle и Sybase, как запросить информацию из БД и использовать её в Вашем приложении, как работать с транзакциями БД и как выполнять хранимые процедуры.

    В главе описано, как настроить Вашу БД для работы с LiveWire Database Service. Вы должны прочесть эту главу и "Информацию Конфигурации", прежде чем начать использовать LiveWire с Вашими приложениями JavaScript.

    В главе описано, как машина выполнения JavaScript на сервере конвертирует сложные типы данных из реляционных БД и простые типы JavaScript.

    В этой главе рассмотрены типы ошибок, которые могут возникнуть при работе с реляционными БД.

    В главе описано приложение-образец videoapp, иллюстрирующее использование службы LiveWire Database Service. Показано, как конфигурировать окружение для запуска приложений videoapp и oldvideo.
    Дата последнего обновления: 29 сентября 1999 г.
    © Copyright © 1999 Sun Microsystems, Inc. Некоторая часть Copyright © 1999 Netscape Communications Corp. Все Права Зарезервированы.

    ЧАСТЬ 4. Работа с LiveConnect.



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

    Число

    Если метод возвращает число, return-значение может представлять число либо статус-код. Например, Cursor.columns возвращает количество столбцов в курсоре, а Cursor.updateRow возвращает число, обозначающее наличие или отсутствие ошибки.
    Методы Cursor.columns и Resultset.columns возвращают числовое значение.
    Следующие методы возвращают число, обозначающее статус-код:
    Connection.beginTransaction
    Connection.commitTransaction
    Connection.execute

    Connection.majorErrorCode
    Connection.minorErrorCode
    Connection.release

    Connection.rollbackTransaction
    Connection.SQLTableCursor.close

    Cursor.deleteRow
    Cursor.insertRow
    Cursor.updateRow
    database.beginTransaction
    database.connect
    database.commitTransaction

    database.disconnect
    database.execute
    database.majorErrorCode
    database.minorErrorCode

    database.rollbackTransaction
    database.SQLTable
    database.storedProcArgs
    DbPool.connect
    DbPool.disconnect
    DbPool.majorErrorCode

    DbPool.minorErrorCode
    DbPool.storedProcArgsResultset.close
    Stproc.close
    Если числовое return-значение метода указывает статус-код, 0 означает успешное выполнение, а ненулевое число указывает на ошибку. Если статус-код ненулевой, Вы можете использовать методы majorErrorCode и majorErrorMessage ассоциированного объекта Connection, database или DbPool для того, чтобы найти информацию об ошибке. В некоторых случаях методы minorErrorCode и minorErrorMessage предоставляют дополнительную информацию об ошибке. О return-значениях этих методов см. .

    Числовые Значения

    Если Вы передаёте числовые типы JavaScript в качестве параметров Java-методам, Java конвертирует эти значения в соответствии с правилами из данной таблицы:

    Тип Java-параметра
    Правила конвертации

    double

    Точное значение переносится в Java без округления и без потери точности или знака.

    lava.lang.Double
    java.lang.Object

    Создаётся новый экземпляр java.lang.Double, и точное значение переносится в Java без округления и без потери точности или знака.

    float

  • Значения округляются до точности float.

  • Значения, которые слишком велики либо малы, округляются до +бесконечности
    или -бесконечности.

  • byte
    char
    int
    long
    short

  • Значения округляются с использованием режима "округление до минус-бесконечности"/round-to-negative-infinity.

  • Значения, которые слишком велики либо малы, дают ошибку времени выполнения.

  • NaN -значения конвертируются до нуля.

  • java.lang.String

    Значения конвертируются в строки. Например,
    237 становится "237"

    boolean

  • 0 и NaN -значения конвертируются в false.

  • Другие значения конвертируются в true.

  • Когда число JavaScript передаётся как параметр в Java-метод, ожидающий экземпляр java.lang.String, это число конвертируется в строку. Используйте операцию == для сравнения результата этой конвертации с другими строковыми значениями.

    Чтение из Файла

    Используйте методы read, readln и readByte для чтения из файла.
    Метод read читает специфицированное количество байтов из файла и возвращает строку.
    fileObj.read(count);
    Здесь fileObj это File -объект, а count это целое число, специфицирующее количество байтов для чтения. Если count специфицирует больше байтов, чем осталось в файле, метод читает до конца файла.
    Метод readln читает следующую строку файла и возвращает её как строку.
    fileObj.readln();
    Здесь fileObj это File -объект. Символы-разделители строк (\r\n в Windows или просто \n в Unix или Macintosh) не включаются в строку. Символ \r пропускается; \n определяет действительный конец строки. Этот компромисс даёт осмысленное поведение на всех платформах.
    Метод readByte читает следующий байт из файла и возвращает числовое значение следующего байта или -1.
    fileObj.readByte();

    Что Делать и Где

    Клиентская среда (браузер) является передним краем работы приложения. В этой среде, к примеру, Вы отображаете HTML-страницы в окне и обслуживаете истории сессий HTML-страниц, отображаемых в браузере в течение сессии. Объекты этой среды, следовательно, обязаны иметь возможность манипулировать страницами, окнами и историей.
    По контрасту, в серверной среде Вы работаете с ресурсами сервера. Например, Вы можете установить соединение с реляционной базой данных, распределить информацию между пользователями приложения или манипулировать файловой системой сервера. Объекты этой среды обязаны иметь возможность манипулировать реляционной БД и файловой системой сервера.
    Кроме того, HTML-страница не отображается на сервере. Она запрашивается на сервере для отображения на клиенте. Запрошенная страница может содержать клиентский JavaScript. Если запрошенная страница является частью приложения JavaScript, сервер может генерировать эту страницу "на лету".
    При разработке приложения JavaScript помните о разнице между клиентской и серверной платформами. Различия показаны в следующей таблице.

    СерверыКлиенты

    Серверы обычно (хотя и не всегда) являются высокопроизводительными рабочими станциями с быстрыми процессорами и возможностью хранения больших объемов информации.

    Клиенты часто (хотя и не всегда) являются настольными системами с маломощными процессорами и относительно небольшим объемом хранимых данных.

    Серверы могут быть перегружены при одновременном доступе тысяч клиентов.

    Клиенты часто - машины одного пользователя, поэтому можно передать часть нагрузки процессинга клиенту.


    Предварительная обработка данных на клиенте также может уменьшить требования к пропускной способности сети, если клиентское приложение может компоновать данные.

    Обычно имеются разные пути распределения приложения между сервером и клиентом. Некоторые задачи могут выполняться только на клиенте или только на сервере; другие могут выполняться на любом из них. Хотя нет какого-то определённого способа определить, что и где делать, Вы может следовать следующим общим правилам:

    Основное правило - использовать клиентский процессинг (тэг SCRIPT) для следующих задач:



  • Проверка ввода пользователя; то есть проверка верности введённых в форму значений


  • Запрос подтверждения пользователя и отображение диалоговых окон или информационных боксов


  • Выполнение агрегатных расчётов (таких как суммирование или вычисление среднего числа) или иной процессинг данных, запрошенных на сервере


  • "Обусловливание" (условная обработка) HTML
  • Выполнение других функций, не требующих информации с сервера


  • Использовать серверный процессинг (тэг SERVER) для следующих задач:

  • Обслуживание серий клиентских запросов


  • Работа с данными, распределёнными по нескольким клиентам или приложениям


  • Доступ к БД или файлам на сервере
  • Вызов внешних библиотек на сервере
  • Динамическая специализация Java-аплетов; например, визуализация данных через использование Java-аплета


  • Служба JavaScript Session Management Service предоставляет объекты для сохранения информации, а клиентский JavaScript преходящ. Клиентские объекты существуют, пока пользователь имеет доступ к странице. Серверы могут объединять информацию от многих клиентов и многих приложений и могут сохранять большие объёмы данных в базе данных. Важно помнить обо всех этих характеристиках при распределении функциональности между клиентом и сервером.

    Что Нового в Этом Релизе

    В релизах 3.x и 4.x версий сервера Netscape Enterprise Server служба LiveWire полностью интегрирована с сервером. Поскольку LiveWire database connectivity теперь интегрирована как LiveWire Database Service - часть серверного JavaScript, разработчикам не нужно устанавливать LiveWire как отдельный продукт. Просто включите поддержку JavaScript в Administration Server, чтобы сделать доступными необходимые компоненты.
    ПРИМЕЧАНИЕ:
    Отличие между SSJS в Netscape Enterprise Server (NES) 3.x и в NES 4.x состоит в том, что NES 4.x использует теперь JavaScript Runtime от Mozilla.org, которая поддерживает JavaScript 1.4. Предыдущие версии SSJS поддерживали JavaScript 1.0, JavaScript 1.1 и JavaScript 1.2.

    Что Такое JavaScript?

    JavaScript это созданный фирмой Netscape межплатформенный, объектно-ориентированный язык скриптинга (сценариев). Ядро JavaScript содержит набор основных объектов, таких как Array, Date и Math, и основной набор элементов языка, таких как операции, структуры управления и операторы. Ядро JavaScript может быть расширено для различных целей путём дополнения новыми объектами; например:
    Клиентский JavaScript расширяет ядро языка, предоставляя объекты управления браузером (Navigator или другой web-браузер) и Document Object Model (DOM). Например, клиентские расширения дают приложению возможность размещать элементы в HTML-форме и реагировать на действия пользователя, такие как щелчок мыши, ввод данных в форму и навигация по страницам.

  • Серверный JavaScript расширяет ядро языка, предоставляя объекты, относящиеся к запуску JavaScript на сервере. Например, серверные расширения дают приложению возможность соединяться с реляционной БД, сохранять информацию между вызовами приложения или выполнять работу с файлами на сервере.

  • JavaScript позволяет создавать приложения, работающие по всей сети Internet. Клиентские приложения работают в браузере, таком как Netscape Navigator, а серверные приложения - на сервере, таком как Netscape Enterprise Server. Используя JavaScript, Вы можете создавать динамические HTML-страницы, обрабатывающие пользовательский ввод и имеющиеся данные, используя специальные объекты, файлы и реляционные БД.
    С помощью функциональности JavaScript LiveConnect Вы можете организовать взаимодействие кодов Java и JavaScript. Из JavaScript Вы можете инстанциировать объекты Java и получать доступ к их public-методам и полям. Из Java Вы можете получать доступ к объектам, свойствам и методам JavaScript.
    Корпорация Netscape изобрела JavaScript, и JavaScript был впервые использован в браузерах Netscape.

    Что Такое LiveConnect?

    LiveConnect даёт возможность подключать приложения серверного JavaScript к Java-компонентам и классам на сервере.
    Вашему приложению JavaScript может понадобиться соединиться с кодом, написанным на других языках, таких как Java или C. Для подключения к Java-коду Вы используете функциональность LiveConnect. Для взаимодействия с кодом, написанным на других языках, у Вас есть несколько вариантов:
    Вы можете обернуть/wrap Ваш код как Java-объект и использовать LiveConnect непосредственно.
  • Вы можете обернуть Ваш код как распределённый объект CORBA и использовать LiveConnect совместно с object request broker (ORB).

  • Вы можете напрямую включать внешние библиотеки в Ваше приложение.

  • В этой главе обсуждается использование LiveConnect для доступа к не-JavaScript коду из приложений JavaScript.
    Наконец, LiveConnect даёт возможность объектам JavaScript Вашего приложения взаимодействовать с Java-объектами. Эти Java-объекты являются экземплярами классов в серверном CLASSPATH. Об установке CLASSPATH см. книгу . LiveConnect работает и с клиентским, и серверным JavaScript, но имеет для каждой среды разные возможности.
    Предполагается, что Вы уже знакомы с программированием на Java. Об использовании Java с Netscape-серверами см. . О LiveConnect см. .
    Во всех доступных Java-классах Вы можете иметь доступ к статичным public-свойствам или методам или создавать экземпляры класса и получать доступ к public-свойствам и методам этих экземпляров. В отличие от клиентского, однако, Вы можете иметь доступ только к тем Java-объектам, которые были созданы Вашим приложением или другим приложением JavaScript, а затем сохранены как свойство объекта server.
    Если Java-объект был создан серверным приложением, отличным от приложения на серверном JavaScript, Вы не можете иметь доступ к этому Java-объекту.

    Например, Вы не можете получить доступ к Java-объекту, созданному WAI plug-in, расширением NSAPI или HTTP-аплетом.
    Когда Вы вызываете метод Java-объекта, Вы можете передать объекты JavaScript в этот метод. Код Java может установить свойства и вызвать методы этих объектов JavaScript. Таким образом, Вы можете иметь и код JavaScript, вызывающий код Java, и код Java, вызывающий код JavaScript.
    Код Java может иметь доступ к приложению JavaScript
    только таким способом. То есть Java-объект не может вызывать приложение JavaScript, если это приложение JavaScript (или другое приложение JavaScript) не имеет само доступа к соответствующему Java-объекту и не вызывает один из его методов.

    Что Вы Уже Должны Знать

    Предполагается, что Вы уже имеете следующие базовые знания:
    Общее представление об Internet и World Wide Web (WWW).

  • Общее представление о клиентском JavaScript. Эта книга не дублирует информацию ядра/core языка или клиентского языка/client-side.

  • Хорошие рабочие знания Hypertext Markup Language (HTML). Опыт работы с формами и Common Gateway Interface (CGI) также пригодится.

  • Некоторый опыт программирования на Pascal, C, Perl, Visual Basic или аналогичном языке.
  • Если Вы будете использовать службу LiveWire Database Service - знакомство с реляционными базами данных и рабочие знания Structured Query Language (SQL).


  • Client cookie/клиентская "кука"

    Один из методов, используемых в JavaScript для работы со свойствами client -объекта. Этот метод хранит пары имя/значение (куки) на клиентской машине.

    Client-side JavaScript/клиентский JavaScript

    Ядро JavaScript плюс расширения, управляющие браузером (Navigator или иной web-браузер), и его DOM. Например, клиентские расширения позволяют приложению размещать элементы в HTML-форме и отвечать на пользовательские события, такие как щелчок мыши, ввод данных в форму и навигация по страницам. См. также , .

    Client URL encoding/клиентская кодировка URL

    Один из методов, который в JavaScript используется для работы со свойствами client -объекта. Этот метод присоединяет пары имя/значение к строке URL.

    Commit/подтвердить

    Чтобы выполнит все действия с БД в транзакции; попытка подтверждения может быть успешной или может потерпеть неудачу, в зависимости от акции и статуса БД.

    Cookie/кука

    Механизм, с помощью которого Navigator-клиент может сохранять небольшие куски информации на клиентской машине.

    CORBA. Клиентский и Серверный Процессы

    показывает две основные части flexi. Они реализуют клиента и сервис CORBA.
    Рисунок 22.2 Приложение-Образец flexi

    CORBA. Клиентский и Серверный Процессы
    Клиент CORBA это приложение на серверном JavaScript, известное как flexi. Это приложение реализует пользовательские интерфейсы администратора и служащего, описанные ранее. Оно соединяется с объектом FSA-Admin (описанном далее) в отдельном процессе или даже на отдельном компьютере. Приложение затем использует этот и другие объекты, возвращаемые из FSA-Admin, для выполнения большинства своих операций.
    Сервер CORBA это отдельное Java-приложение, работающее из оболочки/shell. Оно содержит реализации всех интерфейсов, определённых в IDL-файле Flexi.idl. Это приложение под названием FlexiServer реализует основную функциональность системы FSA. После старта это приложение создаёт экземпляр объекта, реализующий интерфейс ::FSA::Admin, и регистрирует его под именем "FSA-Admin." Клиенты этого сервиса (такие как приложение flexi на JavaScript) получают доступ к этому объекту, разрешая сначала своё имя. Клиенты используют этот объект для создания других объектов и для получения удалённых ссылок на них.

    CORBA

    Common Object Request Broker Architecture. Стандарт, разработанный группой OMG (Object Management Group), программа Object Request Broker (ORB), которая обслуживает взаимодействие между объектами в распределённой компьютерной среде.

    Core JavaScript/ядро JavaScript

    Элементы, общие для клиентского и для серверного JavaScript. Ядро JavaScript содержит основной набор объектов, таких как Array, Date и Math, и основной набор элементов языка, таких как операции, структуры управления и операторы. См. также , .

    Critical section/критичный блок (раздел)

    Участок кода, в котором вам нужен исключительный доступ к объекту или свойству, чтобы убедиться в целостности данных.

    Current row/текущий ряд

    Ряд в таблице, к которому обращается курсор базы данных.

    Current transaction/текущая транзакция

    В приложении базы данных - активная транзакция, в которой выполняются все акции БД.

    Cursor/курсор

    Структура данных, возвращаемых запросом к БД, состоящая из виртуальной таблицы и указателя на ряд в этой таблице; объект Cursor в JavaScript имеет соответствующие свойства и методы.

    у вас должен быть Netscape

    Для использования DB2-сервера у вас должен быть Netscape Enterprise Server. Вы не можете получить доступ к DB2 из Netscape FastTrack Server.

    Все платформы: Установить DB2-клиент версии 2.1.2. Для Solaris Вам нужен APAR #JR10150. См. DB2-документацию .

    Если серверы БД и web находятся на разных машинах: Чтобы определить возможность соединения с DB2-сервером, вы можете выполнить следующую команду из командной строки DB2:

    DB2 TERMINATE # эта команда даёт возможность работы команды catalog

    DB2 CONNECT TO имяБД USERID idпользователя USING пароль

    Если вы используете в приложении типы данных BLOB или CLOB, вы обязаны установить опцию longdatacompat в Вашем файле $DB2PATH/db2cli.ini в 1. Например:

    [Database name]
    longdatacompat=1

    Если Вы сделали изменения в файле db2cli.ini, Вы обязаны рестартовать Ваш web-сервер, чтобы они начали действовать.

    Только для Unix: Вы обязаны установить следующие переменные окружения/environment variables:

    DB2INSTANCE Специфицирует имя порта соединения, определённое и на сервере, и на клиенте. Это имя имеется также и в файле конфигурации dbm для параметра конфигурации SVCENAME.
    DB2PATH Специфицирует директорию верхнего уровня, в которой установлен DB2.

    Например: /home/$DB2INSTANCE/sqllib
    DB2COMM Проверяет, что данная переменная специфицирует протокол, который будет использоваться. Например:

    DB2COMM=TCPIP
    PATH Обязана включать пути $DB2PATH/misc:$DB2PATH/adm:$DB2PATH/bin
    LD_LIBRARY_PATH (Solaris и Irix) Обязана включать директорию DB2 lib. Например, на Solaris обязана включать /opt/IBMdb2/v2.1/lib.
    SHLIB_PATH (HP-UX) Обязана включать директорию DB2 lib.
    LIBPATH (AIX) Обязана включать директорию DB2 lib.


    SQL-файлы для создания видео-БД в DB2, находятся в двух директориях:

    $NSHOME\js\samples\videoapp\db2
    $NSHOME\js\samples\oldvideo\db2

  • (Только в Unix) Ваша переменная окружения PATH обязана содержать директории $DB2PATH/bin, $DB2PATH/misc и $DB2PATH/adm.
  • Прежде чем запустить эти скрипты, Вы обязаны уже иметь установленный DB2 Software Developer's Kit (DB2 SDK).


  • Также, прежде чем Вы сможете запустить скрипты для создания таблиц, Вы обязаны отредактировать их, чтобы изменить некоторые параметры. В Unix это скрипт db2_load.csh; в NT это скрипт db2_load.bat. Отредактируйте соответствующий файл db2_load и измените следующие параметры, отражающие Ваше окружение:
  • : псевдоним имени узла/node name alias


  • : имя хоста узла, где находится целевая БД
  • : имя службы или имя экземпляра из файлов службы
  • : имя БД
  • : авторизованный пользователь
  • : пароль пользователя


  • Убедитесь, что Ваши файлы /etc/services имеют вхождения для экземпляра или имени службы, если Вы создаёте БД на удалённом DB2-сервере.


  • Запустите соответствующую версию скрипта из окна команд DB2. Скрипт db2_load запускает скрипты db2_video.sql и import.sql. Эти вспомогательные скрипты создают видео-таблицы и загружают их данными из файлов *.del. Они не создают новую БД. Они создают таблицы DB2 в псевдониме локальной БД, специфицированном в скрипте db2_load.


  • ПРИМЕЧАНИЕ:

    Если у Вас на машине установлены и DB2, и Sybase или MS SQL Server, потенциально может возникнуть конфликт имён. Эти производители поставляют утилиты с одинаковыми названиями (bcp и isql). При запуске этих скриптов убедитесь, что переменная окружения настроена для запуска корректной утилиты.

    DDL

    Data Definition Language. Операторы БД для создания, изменения или удаления объектов БД, таких как таблицы, ключи, хранимые процедуры и т.д.

    Deadlock/мёртвая блокировка/тупик

    Ситуация с двумя процессами, когда каждый из них ожидает окончания работы другого, чтобы иметь возможность продолжить свою. Соответственно, пока они ожидают друг друга, ни один из них не может функционировать.

    Default page/страница по умолчанию

    Страница, специфицированная в Application Manager, доступ к которой клиент получает, введя URL приложения, но не указав какую-то специфическую страницу приложения. Сравните с .

    Deploy/публиковать

    Перенести приложение туда, где другие пользователи могут получить к нему доступ. Это может быть место в локальной файловой системе или на удалённом сервере, подключённом к Internet.

    Deployment server/сервер публикации

    Сервер, на котором установлено приложение JavaScript, к которому (серверу) осуществляют доступ пользователи; называется также production server. Это не должен быть сервер разработки.

    Deprecate/не рекомендуется (применять)

    Не рекомендуется использование данной возможности, но без удаления её из продукта. Когда возможность JavaScript не рекомендуется, обычно предлагается альтернатива; Вы не должны в дальнейшем использовать нерекомендуемые возможности, поскольку в последующих релизах они могут быть удалены.

    Development server/сервер разработки

    Сервер, обычно в зоне прокси-сервера, на котором Вы разрабатываете и тестируете приложения JavaScript, недоступный конечным пользователям. Это не должен быть сервер публикации.

    DML

    Data Manipulation Language. Операторы БД для выбора, обновления, вставки или удаления рядов таблиц.

    Документация JavaScript и Спецификация ECMA

    Спецификация ECMA это набор требований по реализации ECMAScript; она применима, если Вам необходимо определить, поддерживается ли возможность из JavaScript в ECMA. Если Вы планируете написать код JavaScript, использующий только возможности, поддерживаемые ECMA, Вам может понадобиться просмотреть спецификацию ECMA.
    Документ ECMA не предназначен для помощи программистам скриптов; для этого используйте документацию JavaScript.

    Доступ к JavaScript с Помощью JSObject

    Предположим, к примеру, что вы работаете с Java-классом JavaDog. Как показано в следующем коде, конструктор JavaDog constructor принимает JavaScript-объект jsDog, который определён как имеющий тип JSObject, в качестве аргумента:
    import netscape.javascript.*;

    public class JavaDog
    {

    public String dogBreed;
    public String dogColor;
    public String dogSex;

    // определить конструктор класса

    public JavaDog(JSObject jsDog)
    {

    // использовать try...catch для обработки JSExceptions

    this.dogBreed = (String)jsDog.getMember("breed");

    this.dogColor = (String)jsDog.getMember("color");

    this.dogSex = (String)jsDog.getMember("sex");

    }
    }
    Обратите внимание, что метод getMember объекта JSObject используется для доступа к свойствам объекта JavaScript. Предыдущий пример использует getMember для присвоения значения JavaScript-свойства jsDog.breed члену данных Java JavaDog.dogBreed.
    ПРИМЕЧАНИЕ:
    Более жизненный пример помещает вызов getMember в блок try...catch для обработки ошибок типа JSException. См. .
    Чтобы лучше понять, как работает getMember, посмотрим на определение специального JavaScript-объекта Dog:
    function Dog(breed,color,sex) {
    this.breed = breed
    this.color = color
    this.sex = sex
    }
    Вы можете создать JavaScript-экземпляр Dog под названием gabby:
    gabby = new Dog("lab","chocolate","female")
    Если Вы вычислите свойство gabby.color, Вы увидите, что оно имеет значение "chocolate". Теперь предположим, что Вы создаёте экземпляр JavaDog в вашем JavaScript-коде, передавая объект gabby -конструктору:
    javaDog = new Packages.JavaDog(gabby)
    Если Вы вычислите javaDog.dogColor, Вы увидите, что оно также имеет значение "chocolate", поскольку метод getMember в Java-конструкторе присваивает dogColor значение gabby.color.

    Доступ к Переменным CGI

    Как и большинство других web-серверов, серверы Netscape устанавливают значения для определённого набора переменных окружения, называемых CGI-переменными, при установке контекста для запуска CGI-скрипта. Предполагается, что создатели CGI-скриптов могут использовать эти переменные в своих скриптах.
    По контрасту, Netscape web-серверы не устанавливают отдельного окружения для приложений серверного JavaScript. Тем не менее, некоторая часть информации, обычно устанавливаемой в CGI-переменных, может использоваться в приложениях JavaScript. Машина выполнения предоставляет несколько механизмов для доступа к этой информации:
  • Через доступ к свойствам предопределённого объекта request

  • Через использование функции ssjs_getCGIVariable для доступа к некоторым CGI-переменным и другим переменным окружения

  • Через использование метода httpHeader объекта request для доступа к свойствам шапки клиентского запроса

  • В следующей таблице перечислены свойства объекта request, соответствующие CGI-переменным. Дополнительно об этих свойствах и об объекте request в целом см. .

    CGI-переменная
    СвойствоОписание
    AUTH_TYPE
    auth_type

    Тип авторизации, если запрос защищён авторизацией любого типа. Netscape web-серверы поддерживают базовую авторизацию доступа HTTP.

    Пример значения: basic
    REMOTE_USER
    auth_user

    Имя локального HTTP-пользователь web-браузера, если авторизации доступа HTTP была активирована для данного URL. Заметьте, что это не способ определения имени пользователя, получившего доступ к Вашей программе. Пример значения: ksmith
    REQUEST_METHOD method
    HTTP-метод, ассоциированный с запросом. Приложение может использовать его для определения соответствующего ответа на запрос.

    Пример значения: GET
    SERVER_PROTOCOL protocol
    Уровень протокола HTTP, поддерживаемый клиентским программным обеспечением. Пример значения: HTTP/1.0
    QUERY_STRING query
    Информация запрашивающей HTML-страницы; если имеется "?", информация в URL, идущая после знака "?". Пример значения: x=42


    Серверная функция ssjs_getCGIVariable даёт Вам доступ к переменным окружения, установленным в серверном процессе, включая CGI-переменные, перечисленные в следующей таблице.

    Переменная

    Описание
    AUTH_TYPE

    Тип авторизации, если запрос защищён авторизацией любого типа. Netscape web-серверы поддерживают базовую авторизацию доступа HTTP.

    Пример значения: basic
    HTTPS

    Если на сервере активна служба безопасности/security, значение этой переменной ON; иначе - OFF. Пример значения: ON
    HTTPS_KEYSIZE

    Количество битов в ключе сессии, используемом для шифрования сессии, если безопасность on. Пример значения: 128
    HTTPS_SECRETKEYSIZE

    Количество битов, используемых для генерации private-ключа сервера.

    Пример значения: 128
    PATH_INFO

    Информация пути, установленная браузером. Пример: /cgivars/cgivars.html
    PATH_TRANSLATED

    Фактическое системное pathname/имя пути , содержащегося в PATH_INFO. Пример: /usr/ns-home/myhttpd/js/samples/cgivars/cgivars.html
    QUERY_STRING

    Информация запрашивающей HTML-страницы; если имеется "?", информация в URL, идущая после знака "?". Пример значения: x=42
    REMOTE_ADDR

    IP-адрес хоста, отправившего запрос. Пример: 198.93.95.47
    REMOTE_HOST

    Если DNS на сервере включена, имя хоста, отправившего запрос; иначе - его IP-адрес. Пример: www.netscape.com
    REMOTE_USER

    Имя локального HTTP-пользователя web-браузера, если авторизация доступа HTTP была активирована данным URL. Заметьте, что это не способ определения user name того, кто выполнил доступ к Вашей программе. Пример: ksmith
    REQUEST_METHOD

    HTTP-метод, ассоциированный с запросом. Приложение может использовать его для определения ответа на запрос. Пример: GET
    SCRIPT_NAME

    pathname к данной странице, как он введён в URL. Пример: cgivars.html
    SERVER_NAME

    hostname или IP-адрес, по которому приложение JavaScript запущено, как они даны в URL. Пример: piccolo.mcom.com
    SERVER_PORT

    TCP-порт, по которому запущен сервер. Пример: 2020
    SERVER_PROTOCOL

    Уровень протокола HTTP, поддерживаемый клиентским программным обеспечением. Пример: HTTP/1.0
    SERVER_URL

    URL, введённый пользователем для доступа к данному серверу. Пример: https://piccolo:2020
    <


    Здесь приведён синтаксис ssjs_getCGIVariable:

    value = ssjs_getCGIVariable("name");

    Этот оператор устанавливает в переменную value значение CGI- переменной name. Если предоставленный вами аргумент не является одной из CGI-переменных, перечисленных в , машина выполнения ищет переменную окружения с этим именем в среде сервера. Если она найдена, машина выполнения возвращает значение; иначе, возвращает null. Например, следующий код присваивает значение стандартной переменной окружения CLASSPATH переменной JavaScript classpath:

    classpath = ssjs_getCGIVariable("CLASSPATH");

    Метод httpHeader объекта request возвращает шапку/header текущего клиентского запроса. Для CGI-скрипта Netscape web-серверы устанавливают CGI-переменные для некоторой информации в шапке. Для приложений JavaScript Вы получаете эту информацию непосредственно из шапки. показывает информацию, доступную как переменные CGI в среде CGI, но как свойства шапки - в серверном JavaScript. В свойствах шапки символы подчёркивания в имени CGI-переменной (_) заменяются на тире (-); например, CGI-переменная CONTENT_LENGTH соответствует свойству шапки content-length.

    CGI-переменнаяОписание
    CONTENT_LENGTH

    Количество байтов, отправленных клиентом.
    CONTENT_TYPE

    Тип данных, отправленных клиентом, если форма отправлена методом POST.
    HTTP_ACCEPT

    Перечисляет типы данных, которые может принимать клиент.
    HTTP_USER_AGENT

    Идентифицирует браузер, используемый для доступа к Вашей программе.
    HTTP_IF_MODIFIED_SINCE

    Дата, установленная в соответствии со стандартным временем GMT (по Гринвичу), дающая возможность отправлять клиенту ответ на запрос только тогда, когда дата была изменена после данной даты.
    Дополнительно о манипулировании клиентской "шапкой" см. .

    В таблице даны CGI-переменные, не поддерживаемые серверным JavaScript, которые не могут быть применены при запуске приложений JavaScript.

    ПеременнаяОписание
    GATEWAY_INTERFACE

    Версия CGI, запущенная на сервере. Не применяется к приложениям JavaScript.
    SERVER_SOFTWARE

    Тип запущенного сервера. Недоступна для приложений JavaScript.

    Доступ к Серверному JavaScript

    Рассмотрим теперь использование Java для доступа к серверному JavaScript. Для того чтобы метод Java получил доступ к объектам JavaScript, он обязан быть вызван из приложения, написанном на серверном JavaScript. В клиентском JavaScript, Java может инициировать взаимодействие с JavaScript. На сервере Java не может инициировать это взаимодействие.
    ПРИМЕЧАНИЕ:
    Когда Вы рекомпилируете Java-класс, который используется в приложении JavaScript, новое определение может не иметь немедленного эффекта. Если любое приложение JavaScript, запущенное на web-сервере, имеет "живую" ссылку на объект, созданный из старого определения класса, все приложения продолжают использовать старое определение. Поэтому при рекомпилировании Java-класса Вы должны рестартовать любые приложения JavaScript, имеющие доступ к этому классу.

    Доступ к Значениям Формы

    Формы это альфа и омега приложений на JavaScript. Вы используете такие элементы формы как текстовые поля и радио-кнопки в качестве первичного механизма переноса данных с клиента на сервер. Когда пользователь щёлкает на кнопке Submit, браузер отправляет значения, введённые форму, на сервер для обработки.
    Атрибут ACTION тэга FORM определяет приложение, которому отправляются значения. Для того чтобы отправить информацию приложению на сервер, используйте URL приложения как значение атрибута ACTION.
    Если документ, содержащий форму, является скомпилированной частью того же самого приложения, Вы можете просто предоставить имя страницы вместо полного URL. Например, вот тэг FORM из приложения-примера Hangman:

    Формы, отправляемые приложениям на серверном JavaScript, могут использовать get или post в качестве значения атрибута METHOD.
    ПРИМЕЧАНИЕ:
    Приложения на серверном JavaScript не поддерживают автоматическую выгрузку файлов. То есть, если специфицированная action это страница в приложении JavaScript, Вы отправляете элемент INPUT с типом TYPE="file", Ваше приложение обязано само обработать этот файл, как описано в разделе Каждый элемент ввода HTML-формы соответствует свойству объекта request. Имя свойства специфицируется атрибутом NAME элемента формы. Например, следующий HTML создаёт свойство объекта request под названием guess, которое принимает одиночный символ в текстовом поле. Вы обращаетесь к этому свойству в серверном JavaScript как к request.guess.



    What is your guess?

    Элемент SELECT, дающий возможность множественного выбора, требует особого обращения, поскольку это единственное свойство, которое может иметь несколько значений. Вы можете использовать функцию getOptionValue для получения значений выбранных опций в списке множественного выбора. Дополнительно см. .

    Информацию об объекте request см. в разделе .

    Если Вы хотите обработать данные сначала на стороне клиента, Вы должны создать функцию клиентского JavaScript для выполнения обработки значений элементов формы и передать затем вывод клиентской функции элементу формы. Вы можете скрыть/hide этот элемент, чтобы он не отображался пользователю, если Вы хотите выполнить клиентский препроцессинг.

    Например, у Вас имеется функция клиентского JavaScript под названием calc, выполняющая расчёт на основе пользовательского ввода. Вы хотите передать результат работы этой функции Вашему приложению для дальнейшей обработки. Сначала Вам нужно определить скрытый элемент формы для результата:



    Затем Вам нужно создать обработчик события onClick для кнопки Submit, который назначает вывод функции в скрытый элемент:


    onClick="this.form.result.value=calc(this.form)">

    Значение элемента result отправляется вместе с другими значениями элементов формы. Обратиться к этому значению в приложении можно request.result.

    Другие Куки

    Когда серверу высылается запрос на страницу приложения JavaScript, шапка/header запроса включает все куки, установленные в данный момент для приложения. Можно использовать метод request.httpHeader для доступа к этим кукам из серверного JavaScript и присвоения их значений серверным переменным. И наоборот, Вы можете использовать функцию addResponseHeader для добавления новых кук в ответ, высылаемый обратно клиенту. Эта функциональность описана в разделе .
    На клиентской стороне Вы можете использовать функцию вроде приведённой здесь для доступа к куке:
    function GetCookie (name) {
    var arg = name + "=";

    var alen = arg.length;
    var clen = document.cookie.length;

    var i = 0;
    while (i < clen) {

    var j = i + alen;

    if (document.cookie.substring(i, j) == arg) {

    var end = document.cookie.indexOf (";", j);

    if (end == -1)

    end = document.cookie.length;

    return unescape(document.cookie.substring(j, end));

    }

    i = document.cookie.indexOf(" ", i) + 1;

    if (i == 0) break;
    }

    return null;
    }
    И Вы может использовать функцию типа приведённой ниже для установки куки на клиенте:
    function setCookie (name, value, expires, path, domain, secure) {

    document.cookie =
    name + "="

    + escape(value)

    + ((expires) ? "; expires=" + expires.toGMTString() : "")

    + ((path) ? "; path=" + path : "")

    + ((domain) ? "; domain=" + domain : "")

    + ((secure) ? "; secure" : "");
    }
    Если путь, специфицированный Вами для куки, находится в Вашем приложении JavaScript, то эта кука будет отправлена в ответ на любой запрос к приложению.
    Вы можете использовать эту технику для передачи информации куки между клиентом и сервером, независимо от вида используемой техники работы с объектом client.

    Другие Объекты JavaScript

    Если вы передаёте любой другой объект JavaScript в качестве параметра Java-методу, Java конвертирует объект в соответствии с правилами из таблицы:
    Тип Java-параметраПравила конвертации

    java.lang.JSObject
    java.lang.Object

    Объект оборачивается в новый экземпляр java.lang.JSObject.

    java.lang.String
    Оболочка с объекта снимается, вызывается метод toString развёрнутого Java-объекта, а результат возвращается как новый экземпляр java.lang.String.

    byte
    char
    double
    float
    int
    long
    short
    Объект конвертируется в значение с использованием логики оператора ToPrimitive, описанного в . Подсказка PreferredType, используемая с этим оператором, это Number.

    boolean
    Оболочка с объекта снимается, и возникает одна из следующих ситуаций:
    Если развёрнутый объект имеет метод booleanValue, исходный объект конвертируется в return-значение.

  • Если объект не имеет метода booleanValue, конвертация терпит неудачу.


  • ECMA

    European Computer Manufacturers Association. Международная ассоциация стандартов информационных и коммуникационных систем.

    ECMAScript

    Стандартизованный международный язык программирования на базе ядра JavaScript. Эта стандартизованная версия JavaScript работает одинаково во всех приложениях, поддерживающих данный стандарт. Компании могут использовать открытый стандартный язык для разработки своих реализаций JavaScript. См. также .

    External function/внешняя функция

    Функция, определённая во внешней библиотеке и используемая в приложении JavaScript.

    Где Найти Информацию о JavaScript

    Поскольку JavaScript может применяться на разных уровнях, документация по нему разделена на несколько книг. Набор онлайновых книг по JavaScript включает:
    Документацию по JavaScript, состоящую из следующих книг:
  • Серверный JavaScript. Руководство. (эта книга) предоставляет информацию о языке JavaScript и его объектах. Эта книга содержит информацию о ядре языка (версии 1.4) и о серверном JavaScript. Работа некоторых возможностей ядра на клиенте отличается от их работы на сервере; эти отличия обсуждаются в данной книге.

  • Серверный JavaScript. Справочник. предоставляет справочный материал по языку JavaScript, включая ядро и серверный JavaScript.

  • Если Вы новичок в JavaScript, начните с . После того как Вы будете иметь твёрдое понимание основ, можете воспользоваться книгой
    Серверный JavaScript, Справочник.
    для получения долее детальной информации об объектах и операторах.
    Используйте материал этой книги для знакомства с ядром и серверным JavaScript. Пользуйтесь книгами
    Клиентский JavaScript. Руководство.
    и
    Клиентский JavaScript. Справочник. для получения информации о создании сценариев на HTML-страницах.
    содержат информацию о Enterprise Server 4.x, в том числе - касающуюся серверного JavaScript для Enterprise Server 4.x.
    Книга содержит резюме по разным интерфейсам программирования, доступным в версиях 4.x Netscape web-серверов. Используйте это учебник в качестве карты или отправной точки при изучении документации Enterprise Server для разработчиков.
    Помимо этого, другие книги Netscape обсуждают отдельные аспекты JavaScript, особенно относящиеся к их области действия. Эти книги упоминаются в тексте данной книги там, где это возможно.
    Сайт Netscape содержит большое количество информации, которая может понадобиться при создании приложений JavaScript. Вот некоторые URL, представляющие особый интерес:


  • Страница технической поддержки Netscape службы LiveWire Database Service. Содержит много ссылок на информацию по использованию LiveWire в приложениях JavaScript.



  • Страница технической поддержки Netscape с информацией о JavaScript. Для быстрого перехода на эту страницу щёлкните ссылку DevEdge в Netscape Enterprise Server Application Manager.



  • Это View Source Magazine, онлайновый магазин для разработчиков. Он обновляется каждую неделю и часто содержит статьи, представляющие интерес для разработчиков JavaScript.

    Генерирование HTML

    Как уже было сказано ранее в этой главе, функция write генерирует HTML на основе значения выражения JavaScript, заданного в качестве аргумента. Например, рассмотрим оператор:
    write("Customer Name is:" + project.custname + ".");
    В ответ на этот оператор JavaScript генерирует HTML, вставляя тэг параграфа и некоторый текст, соединённый со значением свойства custname объекта project. Например, если свойство будет иметь значение "Fred's software company", клиент получит следующий HTML:
    Customer Name is: Fred's software company.
    Как кажется клиенту, это нормальный HTML. Однако он в действительности динамически сгенерирован машиной выполнения JavaScript.

    Конфигурирование Базы Данных

    В этой главе рассматривается настройка Вашей Базы Данных для запуска со службой LiveWire Database Service. Вы должны прочесть эту главу и раздел перед тем как использовать LiveWire с Вашими JavaScript-приложениями.
    ПРИМЕЧАНИЕ:

    Могут понадобиться изменения в клиентах БД. Дополнительно см. .
    В этой главе имеются следующие разделы:


  • Конвертация Типов Данных

    В этой главе рассматривается, как машина выполнения JavaScript на сервере конвертирует более сложные типы данных, используемые в реляционных БД, и простые типы.
    В главе имеются следующие разделы:



  • Обработка Ошибок LiveWire

    В этой главе рассмотрены типы ошибок, которые могут появиться при работе с реляционными БД.
    В главе имеются следующие разделы:




  • Приложения-Образцы Videoapp и Oldvideo

    В этой главе описано приложение-образец videoapp, иллюстрирующее использование службы LiveWire Database Service. Рассмотрено, как сконфигурировать рабочую среду для запуска приложений videoapp и oldvideo.
    В главе имеются следующие разделы:




  • LiveConnect. Обзор.

    В этой главе рассматривается использование технологии LiveConnect для взаимодействия кодов, написанных на Java и JavaScript. Предполагается, что Вы уже знакомы с программированием на Java.
    В главе имеются следующие разделы:

  • Дополнительно об использовании LiveConnect см.
    на сайте DevEdge, а также ищите соответствующую информацию на сайтах mozilla.org и developer.netscape.com.

    JavaScript. Обзор.

    Это введение в JavaScript и обсуждение некоторых фундаментальных понятий.
    В главе имеются следующие разделы:







  • Доступ к Сервису CORBA

    В этой главе рассматривается использование LiveConnect для доступа к распределённым объектам CORBA. С помощью LiveConnect Вы можете получить доступ к Java; через Java - соединяться с CORBA-объектами, используя Netscape Internet Service Broker for Java.
    В главе имеются следующие разделы:




  • В этой главе дан обзор

    В этой главе дан обзор типичного приложения на языке "Серверный JavaScript" и показано, как настроить систему для разработки серверных приложений.
    В главе имеются следующие разделы:





  • Технология Разработки Приложений JavaScript

    В этой главе рассматриваются вопросы процесса разработки Вашего приложения, такие как использование компилятора приложений JavaScript и Менеджера Приложений Netscape-серверов для инсталяции или отладки Вашего приложения.

    Информацию об использовании только клиентского JavaScript см. в книге Клиентский JavaScript 1.3. Руководство.
    В этой главе имеются следующие разделы:



  • Быстрое Начало с Примерами Приложений

    В этой главе рассматриваются образцы приложений серверного JavaScript, поставляемые вместе с Netscape web-сервером. Это начало работы с JavaScript с использованием двух простейших приложений.
    В данной главе имеются следующие разделы:



  • Основы Серверного JavaScript

    В этой главе даются основы серверной функциональности и различия между клиентским и серверным JavaScript. Здесь показано, как внедрять серверный JavaScript в HTML-файлы. Обсуждается, что происходит во время прогона программы на клиенте и на сервере, чтобы Вы могли разобраться во всём этом. В главе описано, как использовать JavaScript для изменения HTML-страницы, отправляемой клиенту, и, наконец, как распределить информацию между серверными и клиентскими процессами.
    В главе имеются следующие разделы:










  • Серверный JavaScript имеет то же ядро языка, что и клиентский JavaScript, с которым Вы, возможно, уже знакомы. Задачи, выполняемые Вами при запуске JavaScript на сервере, несколько отличаются от задач, выполняемых при работе JavaScript на клиенте. Разные окружения и задачи обращаются к различным объектам.

    Служба Session Management Service

    В этой главе рассматриваются объекты службы Session Management Service, доступные в серверном JavaScript и предназначенные для обеспечения совместного использования данных несколькими клиентскими запросами к приложению, несколькими пользователями одного приложения или даже несколькими приложениями на сервере.
    Session Management Service это набор возможностей для управления созданием и уничтожением различных предопределённых объектов в ходе сессии сервера. Эти возможности предоставлены через объекты request, client, project и server.
    Помимо этого Вы можете конструировать экземпляры Lock для управления доступом к совместно используемой информации. Lock -экземпляры дают возможность точно управлять использованием информации, устанавливая исключительный доступ к специфицированным объектам.
    В главе имеются следующие разделы:







  • Другая Функциональность JavaScript

    В этой главе рассматривается дополнительная функциональность серверного JavaScript, которую Вы можете использовать для отправки e-mail из Вашего приложения, для доступа к файловой системе сервера, подключения внешних библиотек или непосредственного манипулирования клиентскими запросами и клиентскими ответами.
    В главе имеются следующие разделы:



  • Соединение с Базой Данных

    В этой главе обсуждается использование службы LiveWire Database Service для соединения Вашего приложения с реляционными базами данных DB2, Informix, ODBC, Oracle или Sybase. Показано, как выбрать наилучшую методологию для Вашего приложения.
    В главе имеются следующие разделы:







  • Работа с Базой Данных

    В этой главе обсуждается работа с реляционными базами данных DB2, Informix, ODBC, Oracle и Sybase. Рассматривается, как запрашивать информацию из БД и использовать её в приложении, как работать с транзакциями и как выполнять хранимые процедуры.
    Не забывайте, что, если Ваше приложение работает на Netscape FastTrack Server, а не на Netscape Enterprise Server, оно может иметь доступ только к серверам БД, использующим стандарт ODBC.
    В главе имеются следующие разделы:








  • Hangman

    В этом разделе Вы запустите и модифицируете приложение-образец Hangman и получите представление о том, как:
  • Использовать исходные файлы на чистом JavaScript.

  • Исправлять ошибки времени компиляции/compile-time errors.

  • Использовать утилиту трассировки для отладки.

  • Hangman это классическая игра, в которой игроки пытаются угадать слово. Неизвестные буквы отображаются на экране звёздочками; звёздочка заменяется на букву, если игрок угадывает её. Если введённая буква некорректна, прорисовывается часть повешенного. Игра показывает также некорректные буквы, введённые Вами.
    Если повешенный прорисуется полностью, игрок проиграл. Игрок выигрывает, угадав все буквы слова до окончания прорисовки повешенного. В этой упрощённой версии игры есть только три слова для угадывания. После окончания игры можно снова начать её снова (и использовать следующее слово) или закончить игру.
    Запустите приложение Hangman, выбрав Hangman в Application Manager и щёлкнув Run. Можно также загрузить приложение в Navigator:
    http://server.domain/hangman
    В ответ Application Manager выведет страницу, показанную на следующем рисунке.
    Рисунок 4.2Hangman

    Hangman
    Поиграйте в игру, чтобы получить представление о работе программы.

    Hello World

    В этом разделе Вы запустите приложение Hello World, пример простейшего приложения, и получите представление о следующих процедурах:
  • Чтение исходных файлов JavaScript

  • Внедрение JavaScript в HTML

  • Построение/Building и рестарт приложения

  • Чтобы начать работу с образцами приложений, Вам необходим доступ к JavaScript Application Manager. Вы можете получить этот доступ, введя следующий URL в Navigator:
    http://server.domain/appmgr
    В этом и других URL в данном учебнике server это имя сервера, на котором Вы запускаете Ваше приложение, как, например research1 или www, domain это имя домена Internet, такое как netscape.com или uiuc.edu. Если Ваш сервер имеет Secure Sockets Layer (SSL), используйте https вместо http в URL.
    В Application Manager'е выберите world в левом фрэйме и щёлкните кнопку Run. Вы можете также ввести URL приложения в поле Location Navigator'а:
    http://server.domain/world
    Application Manager выведет страницу, показанную на .
    Рисунок 4.1 Hello World

    Hello World
    Об Application Manager см. .

    HTML

    Hypertext Markup Language. Язык разметки, используемый для создания страниц для World Wide Web.

    HTTP

    Hypertext Transfer Protocol. Протокол соединения, используемый для передачи информации между серверами и клиентами web.

    Идентификация Файлов Библиотек

    Прежде чем Вы сможете запустить приложение, использующее функции внешних библиотек, Вы обязаны идентифицировать файлы этих библиотек. Используя Application Manager, Вы можете идентифицировать библиотеки, когда Вы устанавливаете приложение (щёлкнув Add) или когда модифицируете параметры инсталяции приложения (щёлкнув Modify). Дополнительно об идентификации файлов библиотек с помощью Application Manager см. .
    Важно!
    После ввода пути к файлам библиотек в Application Manager Вы обязаны рестартовать сервер, чтобы изменения вступили в силу. Затем необходимо скомпилировать и рестартовать приложение.
    После идентификации внешних библиотек с помощью Application Manager все приложения, запущенные на данном сервере, могут вызывать функции этих библиотек (используя registerCFunction и callC).

    Индивидуальные Соединения с Базой Данных

    Как только Вы создали пул соединений, клиентская страница может получить доступ к индивидуальному соединению из пула. Если Вы используете объект database, соединение в данном объекте является неявным; то есть Вы используете методы объекта database для доступа к соединению. Если, однако, Вы используете объекты DbPool, соединение инкапсулируется в объекте Connection, который Вы получаете через вызов метода объекта DbPool. Например, в следующем пуле:
    project.eng = new DbPool ("ORACLE", "myserver", "ENG", "pwd1", "", 5);
    Вы можете получить соединение из пула с помощью такого вызова метода:
    myconn = project.eng.connection ("My Connection", 60);
    Оба параметра метода являются необязательными. Первый это имя соединения (используется при отладке); второй это целое число, обозначающее таймаут в секундах. В этом примере, если пул имеет доступное соединение или если оно становится доступным в течение 60 секунд, это соединение присваивается переменной myconn. Если соединение не становится доступным в течение указанного периода, этот метод возвращается без соединения. Дополнительно об ожидании получения соединения из пула см. раздел . О том, что делать, если соединение не получено, см. .
    Если Вы закончили использование соединения, возвратите его в пул путём вызова метода release объекта Connection. (Если Вы используете объект database, Вам не нужно самостоятельно освобождать соединение). Прежде чем вызвать метод release, закройте все открытые курсоры, хранимые процедуры и результирующие наборы. Если Вы вызываете метод release, система ожидает, когда всё закроется, и возвращает затем соединение в пул базы данных. После этого соединение доступно следующему пользователю. Об использовании курсоров см. . О хранимых процедурах и результирующих наборах см. .
    После получения соединения (через объект database или объект Connection), Вы можете работать с БД. В таблице резюмированы методы объектов database и connection для работы с единственным соединением. Объект database имеет и другие методы для обслуживания пула соединений, рассмотренные в разделе

    МетодОписание


    cursor


    Создаёт курсор БД для специфицированного оператора SQL SELECT.


    SQLTable


    Отображает результаты выполнения запроса. Создаёт таблицу HTML для результата выполнения оператора SQL SELECT.


    execute


    Выполняет специфицированный оператор SQL. Используется для операторов SQL, отличных от запросов/queries.


    connected


    Возвращает true, если пул БД (и, следовательно, данное соединение) соединён с БД.


    release


    (Только для Connection) Освобождает соединение обратно в пул.


    beginTransaction


    Начинает транзакцию SQL.


    commitTransaction


    Подтверждает текущую транзакцию SQL.


    rollbackTransaction


    Выполняет откат текущей транзакции SQL.


    storedProc


    Создаёт объект хранимой процедуры и запускает специфицированную хранимую процедуру БД.


    majorErrorCode


    Важнейший код ошибки, возвращаемый сервером БД или ODBC.


    majorErrorMessage


    Сообщение о важнейшей ошибке, возвращаемое сервером БД или ODBC.


    minorErrorCode


    Второй по значению код ошибки, возвращаемый библиотекой производителя.


    minorErrorMessage


    Второе по значению сообщение о важнейшей ошибке, возвращаемое библиотекой производителя.

    Информация Конфигурации

    В этом разделе рассматривается информация конфигурации для использования серверного JavaScript. Дополнительно о настройке БД для работы с сервисом LiveWire Database Service см.

    Informix

    При использовании сервера Informix Вы обязаны иметь Netscape Enterprise Server. Вы не можете получить доступ к Informix из Netscape FastTrack Server.
    Если серверы БД и web находятся на разных машинах, следуйте инструкциям раздела
    Если серверы БД и web находятся на одной машине, следуйте инструкциям раздела

    Прежде чем использовать нижеуказанные инструкции, Вы обязаны сконфигурировать Ваш Informix-клиент, как указано в разделе Кроме того, убедитесь, что переменная окружения PATH содержит путь к $INFORMIXDIR\bin и что Ваш клиент сконфигурирован для использования утилит Informix.
    SQL-файлы для создания видео-БД (lw_video) в Informix находятся в двух директориях:
    $NSHOME\js\samples\videoapp\ifx
    $NSHOME\js\samples\oldvideo\ifx
    ПРИМЕЧАНИЕ:
    Не забудьте, что пути в этом учебнике, если они относятся и к NT, и к Unix, даются в формате NT. В Unix Вы используете $NSHOME/js/samples/videoapp/ifx.
  • В Unix войдите в систему как пользователь "informix" и запустите скрипт оболочки ifx_load.csh для videoapp и для oldvideo.


  • В NT дважды щёлкните в группе программ Informix Server иконку Command-Line Utilities, чтобы открыть окно DOS, затем запустите следующие команды:cd c:\netscape\server\js\samples\videoapp\ifx
    ifx_load.bat
    Вы можете также запустить эти команды из директории oldvideo\ifx:

  • Теперь Вы можете запускать приложение, сделав предварительно изменения, описанные в разделе .


  • Initial page/начальная страница

    Страница, специфицированная в Application Manager, которую Application Manager запускает, когда приложение первоначально стартует. Сравните с .

    IP address/IP-адрес

    Набор из четырёх чисел в диапазоне от 0 до 255 включительно, разделённых точками, который специфицирует место по протоколу TCP/IP.

    IP address technique/техника IP-адреса

    Один из видов техники, используемой в JavaScript для обслуживания объекта client, когда сервер использует клиентский IP-адрес для обращения к структуре данных, содержащей значения свойств объекта client.

    Исходные Файлы

    В таблице показаны первичные файлы и директории для flexi.

    flexi.idl
    Файл, определяющий интерфейс с удалённым сервисом, включая Admin, Account, Claim.
    Flexi\
    Директория, содержащая код, сгенерированный из Flexi.idl программой idl2java. Эта директория содержит каркасы и стабы (каркасы\основы) интерфейсов.
    impl\
    Директория, содержащая Java-реализации всех интерфейсов, определённых во Flexi.idl. Она также содержит класс FlexiServer, реализующий main-программу приложения Java, которое работает как сервис.
    *.html
    Файлы, реализующие серверное приложение JavaScript. Сюда входит также web-файл приложения, flexi.web.

    Просмотрите эти файлы, чтобы добиться полной ясности в вопросах работы приложения. Здесь обсуждаются лишь некоторые детали.

    Исключение Мёртвой Блокировки/Deadlock

    Вы используете замки для защиты критичных участков кода. На практике это означает, что один запрос ожидает, пока другой выполняет критичный код. Вы обязаны соблюдать осторожность при использовании замков для защиты критичных разделов. Если один запрос ожидает освобождения замка, полученного другим запросом, а этот второй запрос ожидает освобождения замка, полученного первым запросом, ни один из запросов не сможет продолжить работу. Эта ситуация называется deadlock/тупик/мертвая блокировка.
    Рассмотрим предыдущий пример обработки заказов потребителей. Предположим, что приложение разрешает два действия. В одном - пользователь вводит нового потребителя; в другом - пользователь вводит новый заказ. Как часть создания нового потребителя приложение также создаёт новый заказ потребителя. Это действие выполняется на одной странице приложения, давая примерно такой код:
    // Создать нового потребителя (customer).

    if ( project.customersLock.lock() ) {
    var id = project.customers.ID;

    id = id + 1;
    project.customers.ID = id;
    // Стартовать новый заказ (order) для этого нового потребителя.

    if ( project.ordersLock.lock() ) {
    var c = project.orders.count;

    c = c + 1;

    project.orders.count = c;

    project.ordersLock.unlock();
    }
    project.customersLock.unlock();
    }
    Во втором типе действия пользователь вводит новый заказ потребителя. Как часть процесса ввода нового заказа: если потребитель ещё не является зарегистрированным потребителем, приложение создаёт нового потребителя. Это действие выполняется на другой странице приложения, где может быть примерно такой код:
    // Стартовать новый заказ.

    if ( project.ordersLock.lock() ) {
    var c = project.orders.count;
    c = c + 1;

    project.orders.count = c;

    if (...код определения неизвестного потребителя...) {

    // Создать нового потребителя.

    // Этот внутренний замок может вызвать проблемы!

    if ( project.customersLock.lock() ) {

    var id = project.customers.ID;
    id = id + 1;

    project.customers.ID = id;

    project.customersLock.unlock();
    }
    }

    project.ordersLock.unlock();
    }

    Заметьте, что каждый из этих фрагментов кода пытается получить второй замок, уже получив один. Это может вызвать проблемы. Предположим, что один поток начинает создание нового потребителя; он получает замок customersLock. В это же самое время другой поток начинает создание нового заказа; он получает замок ordersLock. Теперь первый поток запрашивает замок ordersLock. Поскольку второй поток уже получил этот замок, первый поток должен ждать. Предположим, однако, что второй поток теперь запрашивает замок customersLock. Первый поток уже имеет этот замок, поэтому второй поток должен ждать. Теперь потоки ждут друг друга. Поскольку никто их них не специфицировал таймаут, оба они будут ждать бесконечно.

    В данном случае проблему можно легко устранить. Поскольку значения ID потребителя и номер заказа не зависят один от другого, нет никакого смысла вкладывать замки друг в друга. Вы можете избежать возможных тупиков, переписав оба фрагмента кода. Перепишите первый фрагмент так:

    // Создать нового потребителя.

    if ( project.customersLock.lock() ) {

    var id = project.customers.ID;

    id = id + 1;
    project.customers.ID = id;

    project.customersLock.unlock();
    }

    // Стартовать новый заказ для этого нового потребителя.


    if ( project.ordersLock.lock() ) {

    var c = project.orders.count;
    c = c + 1;

    project.orders.count = c;

    project.ordersLock.unlock();
    }

    Второй фрагмент будет примерно таким:

    // Стартовать новый заказ.

    if ( project.ordersLock.lock() ) {

    var c = project.orders.count;

    c = c + 1;
    project.orders.count = c;

    project.ordersLock.unlock();
    }

    if (...код для определения неизвестного потребителя...) {

    // Создать нового потребителя.

    if ( project.customersLock.lock() ) {

    var id = project.customers.ID;

    id = id + 1;

    project.customers.ID = id;

    project.customersLock.unlock();

    }
    }

    Хотя это и надуманная ситуация, тупики это совершенно реальная проблема, и они могут произойти во многих случаях. Для этого даже не понадобится более одного замка или более одного запроса. Рассмотрим код, в котором две функции запрашивают один и тот же замок:

    function fn1 () {
    if ( project.lock() ) {

    // ... какие-то действия ...

    project.unlock();
    }
    }

    function fn2 () {
    if ( project.lock() ) {

    // ... какие-то другие действия ...

    project.unlock();
    }
    }

    Сам по себе этот код не содержит проблем. Позднее слегка измените его, чтобы fn1 вызывала fn2, уже имея замок, как показано далее:

    function fn1 () {
    if ( project.lock() ) {

    // ... какие-то действия ...

    fn2();
    project.unlock();

    }
    }

    Вот вы и получили тупик/deadlock. Это, конечно, немного смешно, когда единственный запрос ожидает от самого себя освобождения флага!

    Исключения Informix и Sybase

    Хранимые процедуры Informix и Sybase могут возвращать коды ошибки, используя механизм исключений. После того как Вы запустили процедуру на выполнение, Вы можете запрашивать эти коды ошибок и сообщения об ошибках, используя методы majorErrorCode и majorErrorMessage ассоциированного объекта database или Connection.
    Например, у Вас имеется хранимая процедура Informix:
    create procedure usercheck (user varchar(20))
    if user = 'LiveWire' then

    raise exception -746, 0, 'User not Allowed';
    endif
    end procedure
    Если Вы запустите эту процедуру на выполнение, Вы сможете проверять, появилась ли ошибка, а затем получить доступ к коду ошибки и сообщению о ней:
    spobj = connobj.storedProc("usercheck");
    if ( connobj.majorErrorCode() ) {
    write("The procedure returned this error code: " +
    connobj.majorErrorCode());

    write("The procedure returned this error message: " +
    connobj.majorErrorMessage());
    }

    Использование Flexi

    Чтобы стартовать flexi, Вы можете запустить его из Application Manager или ввести следующий URL:
    http://server-name/flexi
    Страница по умолчанию позволяет пользователю идентифицировать себя как администратора или как служащего. Чтобы быстрее прочувствовать то, как работает это приложение, следуйте этому сценарию:
    Администратор создаёт для пользователя баланс.

  • Служащий выбирает счёт.

  • Служащий отправляет запрос.

  • Администратор выбирает счёт служащего.

  • Администратор принимает запрос, что уменьшает баланс счёта служащего, и отправляет чек на запрошенную сумму.
  • Служащий выбирает счёт.
  • Служащий просматривает статус счёта.
  • Администратор выбирает счёт служащего.

  • Администратор удаляет запрос.

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

    Использование Функции debug

    Вы можете использовать функцию debug в Вашем приложении JavaScript для помощи при отслеживании/трассировке проблем в приложении. Функция debug отображает значения для утилиты трассировки. Например, следующий оператор выводит значение свойства guess объекта request в окне трассировки вместе с некоторым идентифицирующим текстом:
    debug ("Current Guess is ", request.guess);

    Использование IP-Адреса

    Техника с использованием IP-адреса индексирует структуру данных на основе IP-адресов приложения и клиента. Эта простая техника является также и самой быстрой, поскольку вообще не требует отправки информации клиенту. Так как индекс базируется на IP-адресах приложения и клиента, эта техника создаёт отдельный индекс для каждой пары приложение/клиент, работающей на сервере.
    Эта техника хорошо работает, когда все клиенты имеют фиксированные IP-адреса. Она работает ненадёжно, если клиент не имеет гарантированно фиксированного IP-адреса, например, если клиент использует протокол Dynamic Host Configuration Protocol (DHCP) или провайдера Internet, который динамически размещает IP-адреса. Эта техника также не работает у клиентов, использующих прокси-сервер, поскольку все пользователи прокси сообщают один и тот же IP-адрес. Поэтому данная техника используется в основном только для приложений Intranet.

    Использование Экземпляров Класса Lock

    Представьте lock (замок/блокировку) как именованный флаг, который Вы обязаны устанавливать перед входом в критичный раздел. Если Вы запрашиваете именованный флаг и кто-то уже имеет его, Вы будете ждать, пока этот второй не освободит флаг. В процессе ожидания Вы не сможете изменять то, что не должны изменять. После получения Вами флага кто-либо ещё будет ожидать и не сможет ничего изменить, пока Вы не освободите флаг. Если возникнет ошибка или таймаут закончится до того, как Вы получите флаг, Вы можете снова вернуться в режим ожидания, либо делать что-нибудь другое, как, например, дать Вашим пользователям знать, что приложение очень занято, чтобы выполнить данную операцию сейчас. Вы не должны вмешиваться в процесс ожидания (изменяя совместно используемую информацию)! иллюстрирует этот процесс.

    Рисунок 6.5 Thread (поток) 2 ожидает, пока thread 1 имеет lock (замок)

    Использование Экземпляров Класса Lock
    В терминах программирования замок/lock представлен экземпляром класса Lock. Вы можете использовать экземпляр класса Lock для получения исключительного доступа к любому совместно используемому объекту. Обычно Вы создаёте экземпляры Lock на начальной странице Вашего приложения (по причинам, которые будет изложены позднее).
    На других страницах, перед критичным для совместно используемого объекта разделом (например, перед разделом, который запрашивает и изменяет значение свойства), Вы вызываете метод lock экземпляра Lock. Если этот метод возвращает true, Вы получаете замок и можете продолжать. В конце критичного раздела Вы вызываете метод unlock Lock -экземпляра.
    Когда клиентский запрос в одиночном потоке выполнения вызывает метод lock, любой другой запрос, вызывающий метод lock для того же Lock -экземпляра, ожидает, пока первый поток не вызовет метод unlock, пока не закончится таймаут или пока не возникнет ошибка. Это верно независимо от того, находится второй запрос в другом потоке для того же клиента или в потоке для другого клиента.
    Если все потоки вызывают метод lock перед попыткой изменения совместно используемого объекта, то лишь один поток в единицу времени может войти в критичный раздел.

    Важно!

    Использование замков находится всецело под управлением разработчика и требует кооперации. Машина выполнения не заставляет Вас ни вызывать lock, ни учитывать блокировку, полученную кем-либо другим. Если Вы не спрашиваете, Вы можете изменять всё что захотите. Поэтому очень важно выработать привычку всегда вызывать lock и unlock при входе и выходе из критичного раздела кода и проверять return-значение метода lock, чтобы гарантировать, что блокировка получена. Можно представлять это в терминах флага: если Вы не запрашиваете флаг, вы не будете находиться в режиме ожидания. Если Вы не находитесь в режиме ожидания, Вы можете изменять то, что изменять нельзя.

    Вы можете создать столько замков, сколько Вам необходимо. Один и тот же замок может использоваться для управления доступом к нескольким объектам, либо каждый объект (или даже каждое свойство) может иметь собственный замок.

    Замок/lock сам по себе является просто объектом JavaScript; Вы можете сохранить ссылку на него в любом другом объекте JavaScript. Таким образом, например, обычной практикой является конструирование экземпляра Lock и сохранение его в объекте project.

    ПРИМЕЧАНИЕ:

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

    Следующий код показывает, как отследить заказы потребителей в совместно используемом объекте project.orders, рассмотренном ранее, и как обновлять project.orders.count каждый раз при получении нового заказа. Включите в начальную страницу приложения такой код:

    // Создать новый Lock и сохранить в project.

    project.ordersLock = new Lock();

    if (! project.ordersLock.isValid()) {

    // Невозможно создать Lock. Перенаправить на страницу обработки ошибок.

    redirect ("sysfailure.htm");
    }

    Этот код создаёт экземпляр класса Lock и проверяет (вызовом метода isValid), не возвращено ли что-нибудь неправильное при его создании. Очень редко Ваш экземпляр Lock конструируется неправильно. Это случается только тогда, когда машина выполнения запущена вне системных ресурсов при создании объекта.


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

    Если, однако, Ваше приложение создаёт замок на какой-либо иной странице, множественные запросы могут вызывать эту страницу в это время. Один запрос может проверять наличие замка и не обнаружить его, в то время как другой запрос создаёт замок, а третий запрос создаёт второй замок. Тем временем первый запрос вызывает метод lock своего объекта. Затем второй запрос вызывает метод lock своего объекта. Оба запроса теперь "думают", что они имеют безопасный доступ к критичному разделу кода и продолжают свою работу, нарушая работу другого.

    После получения верного замка Ваше приложение может продолжать работу. На странице, требующей доступа к критичному разделу, можете ввести такой код:

    // Начало критичного раздела -- получить замок.

    if ( project.ordersLock.lock() ) { var x = project.orders.count;

    x = x + 1;
    project.orders.count = x;

    // Конец критичного раздела -- освободить замок.

    project.ordersLock.unlock();

    }
    else
    redirect("combacklater.htm");

    Этот код запрашивает замок. Если замок получен (то есть, если метод lock возвратил true), выполняется вход в критичный раздел, вносятся изменения и, наконец, замок освобождается. Если метод lock возвращает false, то данный код не получает замка. В этом случае приложение перенаправляет на страницу, которая сообщает, что приложение в данный момент не может выполнить запрос.

    Использование Классов LiveConnect

    Все объекты JavaScript появляются в коде Java как экземпляры netscape.javascript.JSObject. Когда Вы вызываете метод в Вашем Java-коде, Вы можете передать ему JavaScript-объект как один из аргументов. Чтобы сделать это, Вы обязаны определить соответствующий формальный параметр метода как имеющий тип JSObject.
    Таким образом, всегда, когда Вы используете JavaScript-объекты в коде Java, Вы должны помещать вызов JavaScript-объекта внутри блока try...catch, который обрабатывает исключения netscape.javascript.JSException. Это позволяет Вашему Java-коду обрабатывать ошибки при выполнении кода JavaScript, которые появляются в Java как исключения типа JSException.

    Использование Клиентского Кодирования URL

    При использовании техники клиентского кодирования URL машина выполнения на сервере пересылает клиенту свойства и значения объекта client, присоединяя их к каждому URL в генерируемой HTML-странице. Соответственно свойства и их значения пересылаются столько раз, сколько имеется гиперссылок на генерируемой HTML-странице, что приводит к значительному увеличению сетевого трафика.
    Размер строки URL ограничен 4KB. Следовательно, когда Вы используете клиентское кодирование URL, общий размер имён свойств и их значений не может превышать 4KB. Любая информация свыше лимита 4KB будет усекаться.
    Если Вы генерируете URLs динамически или используете функцию redirect, Вы можете добавлять свойства объекта client или другие свойства к URL. Когда Вы вызываете redirect или генерируете URL, компилятор не присоединяет автоматически свойства объекта client. Если присоединение необходимо, используйте функцию addClient. См. раздел .
    В технике клиентского кодирования URL значения свойств добавляются к URL по мере обработки этих URL. Нужно следить, чтобы Ваши URL имели одинаковые свойства и значения. Например, рассмотрим код:

    ...
    client.numwrites = 2;
    write (addClient(

    "Some link"));
    client.numwrites = 3;

    write (addClient(
    "Another link"));
    ...


    Когда машина выполнения обрабатывает первый оператор write, она использует 2 как значение свойства numwrites, а при обработке второго оператора write она использует в качестве значения 3.
    Итак, если Вы используете метод client.destroy в середине страницы, только ссылки, шедшие на странице до вызова этого метода получат значения, присоединённые к URL. Те же, которые идут после вызова этого метода, не имеют присоединённых значений. Следовательно, значения свойств объекта client передаются на некоторые страницы, но не на все. Это может быть нежелательно.
    Если страница имеет ссылку на URL за пределами Вашего приложения, Вам не понадобится присоединять клиентский статус. Тогда не используйте статическую строку в качестве значения HREF. Вместо этого вычисляйте значение. Это предотвратит автоматическое присоединение машиной выполнения клиентского статуса к URL. Например, у вас имеется ссылка:

    Машина выполнения присоединяет свойства объекта client. Чтобы этого не происходило, используйте очень похожую ссылку:

    При этой технике объект client не перестаёт действовать, поскольку существует только в URL-строке, находящейся на клиенте. Следовательно, метод client.expiration не производит никаких действий.
    При клиентском кодировании URL Вы теряете все свойства объекта client, когда отправляете форму, используя метод GET, и когда выполняете доступ к другому приложению. Ещё раз - Вам может быть нужно или не нужно терять эти свойства, в зависимости от потребностей Вашего приложения.
    В отличие от техники клиентских кук, клиентское кодирование URL не требует ни поддержки web-браузером протокола Netscape cookie, ни записи информации на клиентской машине.

    Использование Клиентской Куки/Cookie

    В технике клиентских кук машина выполнения JavaScript на сервере использует протокол Netscape cookie protocol для передачи клиенту свойств объекта client и их значений. Она создаёт по одной куке для каждого свойства объекта client. Свойства высылаются клиенту один раз в шапке/header ответа генерируемой HTML-страницы. Netscape cookie protocol описан в книге Клиентский JavaScript.
    .
    Для исключения конфликтов с другими куками, которые Вы можете создать в Вашем приложении, машина выполнения создаёт имя куки, добавляя NETSCAPE_LIVEWIRE. перед началом имени свойства объекта client. Например, если client имеет свойство custID, машина выполнения создаёт куку под названием NETSCAPE_LIVEWIRE.custID. Когда информация куки высылается клиенту, машина выполнения делает всё необходимое кодирование специальных символов в значении свойства, как описано в книге Клиентский JavaScript.
    .
    Иногда Вашему приложению может понадобиться взаимодействие операторов JavaScript на сервере и на стороне клиента. Поскольку это вид техники высылает клиенту свойства объекта client как куки, Вы можете использовать это как способ облегчить это взаимодействие. См. дополнительно .
    При использовании этой техники машина выполнения сохраняет свойства объекта client, когда она в первый раз очищает внутренний буфер, содержащий сгенерированную HTML-страницу. Исходя из этого, для того чтобы предотвратить потерю любой информации, Вы должны как можно раньше присвоить значения всем свойствам объекта client в скриптах на каждой странице. В особенности Вы должны гарантировать, что свойства объекта client будут высылаться перед тем как (1) машина выполнения сгенерирует 64KB содержимого HTML-страницы (она автоматически очищает буфер вывода в этой точке), (2) Вы вызовете функцию flush для очистки буфера вывода или (3) Вы вызовете функцию redirect для изменения клиентских запросов. Дополнительно см. разделы и .
    По умолчанию, когда Вы используете технику клиентских кук, машина выполнения не устанавливает явно время окончания срока действия кук. В этом случае куки заканчивают работать, когда пользователь закрывает браузер. (Это поведение по умолчанию для всех кук.) Как указано в разделе , Вы можете использовать метод expiration объекта client для изменения срока окончания действия. Если Вы используете client.expiration, машина выполнения устанавливает соответствующий срок окончания работы куки в cookie-файле.

    При использовании техники клиентских кук метод client.destroy уничтожает все значения свойств объекта client, но не влияет на то, что хранится в cookie-файле на клиентской машине. Не используйте для удаления кук из cookie-файла или памяти браузера метод client.destroy; вместо него используйте client.expiration с аргументом 0секунд.

    В целом Netscape-куки имеют нижеследующие ограничения. Эти ограничения применяются тогда, когда Вы используете куки для хранения свойств объекта client:

  • 4KB для каждой куки (включая имя и значение куки). Если одна кука больше 4KB, её вхождение усекается до 4KB. Это может дать неверное значение свойства объекта client.
  • 20 кук на приложение. Если Вы создаёте более 20 для одного приложения, самая старая кука (созданная первой) уничтожается. Поскольку техника клиентских кук создаёт отдельную куку для каждого свойства объекта client, объект client может хранить максимум 20 свойств. Если Вы хотите использовать в Вашем приложении также и другие куки, общее их количество всё равно ограничено числом 20.


  • 300 кук в cookie-файле. Если Вы создадите более 300 кук, самые старые куки (созданные первыми) уничтожаются.


  • Использование Кук

    Куки это механизм, который Вы можете использовать на клиенте для сохранения информации между запросами. эта информация находится в файле с названием cookie.txt (куки-файл), хранящемся на клиентской машине. Протокол Netscape cookie детально описан в книге .
    Вы можете использовать куки для отправки информации в обоих направлениях, от клиента серверу и с сервера клиенту. Куки, высылаемые с клиента, становятся свойствами объекта client или объекта request. Хотя Вы можете выслать с сервера клиенту любое строковое значение в качестве куки, простейший метод будет - отправить свойства объекта client.

    Использование Менеджера Приложений/Application Manager для Отладки

    Для отладки приложения выберите его в списке приложений и щёлкните Debug. Application Manager откроет новое окно Navigator, в котором будет запущено приложение. Запустится также утилита трассировки в отдельном фрэйме, в окне, содержащем приложение, или вообще в другом окне. (Вы можете определить появление отладочного окна при конфигурировании установок по умолчанию для Application Manager, как описано в разделе ).
    Утилита трассировки выведет следующую отладочную информацию:
    значения свойств объектов и аргументов функций отладки, вызываемых приложением

  • значения свойств объектов request и client до и после генерации HTML для страницы

  • значения свойств объектов project и server

  • индикацию присвоения новых значений свойствам

  • индикацию отправки машиной выполнения содержимого клиенту

  • На показано то, что Вы можете увидеть при отладке приложения Hangman.

    Рисунок 3.5 Отладка Приложения Hangman

    Использование Менеджера Приложений/Application Manager для Отладки

    Использование Методов Управления Транзакциями

    Используйте следующие методы объектов database или Connection для явного управления транзакциями:
    beginTransaction стартует новую транзакцию. Все действия, модифицирующие базу данных, группируются в данную транзакцию, называемую текущей транзакцией.

  • commitTransaction подтверждает текущую транзакцию. Этот метод пытается подтвердить все действия, выполненные после последнего вызова метода beginTransaction.

  • rollbackTransaction откатывает текущую транзакцию. Этот метод отменяет все изменения, сделанные с момента последнего вызова метода beginTransaction.
  • Конечно, если Ваша БД не поддерживает транзакции, Вы не сможете использовать их. Например, БД Informix, созданная с использованием опции NO LOG, не поддерживает транзакции, и Вы получите ошибку при использовании данных методов.
    Сервис LiveWire Database Service не поддерживает вложение транзакций. Если Вы вызовете beginTransaction несколько раз до подтверждения или отката первой открытой Вами транзакции, Вы получите ошибку.
    Для объекта database максимум области видимости транзакции ограничен текущим клиентским запросом (HTML-страницей) в приложении. Если приложение существует на странице до вызова метода commitTransaction или rollbackTransaction, то транзакция автоматически подтверждается или откатывается на основе установок параметра commitflag, задаваемого при соединении с БД.
    Для объектов Connection область видимости транзакции ограничена периодом существования этих объектов. Если Вы освобождаете соединение или закрываете пул соединений до вызова методов commitTransaction или rollbackTransaction, то транзакция автоматически подтверждается или откатывается на основе установок параметра commitflag, задаваемого при соединении с БД методом connect или в конструкторе DbPool.
    Если текущая транзакция отсутствует (то есть, если приложение не вызывало beginTransaction), вызовы методов commitTransaction и rollbackTransaction могут привести к ошибке в БД.
    Транзакция может работать с разными объёмами данных. Пример из раздела создаёт одну транзакцию для модифицирования всех рядов курсора. Если в Вашем курсоре небольшое количество рядов, такой подход будет оправданным.
    Если, однако, Ваш курсор возвращает тысячи рядов, Вы можете обработать этот курсор в нескольких транзакциях. Такой подход снизит размер транзакций и улучшит доступ к информации.
    Если Вы разбиваете Ваш процесс на несколько транзакций, убедитесь, что вызов next и ассоциированный вызов updateRow или deleteRow происходят внутри одной транзакции. Если Вы получаете ряд в одной транзакции, завершаете её, а затем пытаетесь обновить или удалить ряд, Вы можете получить ошибку в БД.
    Выбор способа обработки транзакции зависит от целей Вашего приложения. Нужно обратиться к документации создателя БД для получения информации о том, как использовать транзакции для данного типа БД.

    Использование Объекта Admin для Администрирования и Просмотра Новых Счетов

    Код во flexi создаёт другие объекты, кроме объекта Admin, и осуществляет к ним доступ во FlexiServer. Эти объекты создаются путём вызовов метода объекта Admin. Например, если служащий отправляет запрос, новый запрос создаётся в account-empl.html следующим оператором:
    __claim = __account.submitClaim(

    parseFloat(request.claimAmount),
    request.serviceDate,

    request.providerName,
    request.details);
    Этот код вызывает метод submitClaim объекта Account для создания нового запроса служащего. Реализация этого метода в файле impl\Account.java создаёт новый Claim-объект, который регистрируется в ORB и возвращается:
    public Flexi.Claim submitClaim(float amount, String serviceDate,

    String providerName, String details)
    {

    Claim __clm = new Claim(this, amount, serviceDate,
    providerName, details);
    org.omg.CORBA.ORB.init().BOA_init().obj_is_ready(__clm);

    _current_clm = __clm;

    System.out.println("***Created a new claim: " + __clm);
    return __clm;
    };

    Использование Серверной Кодировки URL

    Техника серверного кодирования URL использует длинное уникальное имя, генерируемое машиной выполнения для индексации структуры данных на сервере. В этом случае, вместо того чтобы сделать это генерируемое имя клиентской кукой, сервер присоединяет имя к каждому URL на генерируемой HTML-странице. Следовательно, имя высылается столько раз, сколько имеется ссылок на генерируемой HTML-странице. (Имена и значения свойств не присоединяются к URLs, только генерируемое имя.) Ещё раз: Вы можете получить доступ к этому генерируемому имени с помощью функции ssjs_getClientID, описанной в разделе .
    Если Вы генерируете URLs динамически или используете функцию redirect, Вы можете добавлять свойства к URL. Поэтому, когда Вы вызываете redirect или генерируете URL, компилятор не присоединяет индекс автоматически. Если Вы хотите оставить индекс для свойств объекта client, используйте функцию addClient. См. также .
    Если Ваша страница имеет ссылку на URL вне Вашего приложения, Вам может и не понадобиться присоединение клиентского индекса. Тогда не используйте статическую строку как значение атрибута HREF. Вместо этого вычисляйте это значение. Это предотвратит автоматическое присоединение машиной выполнения клиентского индекса к URL. Например, у Вас имеется ссылка:

    В это случае машина выполнения присоединит индекс объекта client. Чтобы этого не происходило, используйте очень похожую ссылку:

    При серверном кодировании URL вы теряете идентификатор объекта client (и, соответственно, свойства и их значения) при отправке формы с методом GET. Вы можете терять или не терять эти свойств, в зависимости от потребностей Вашего приложения.

    Использование Серверных Кук

    Техника серверных кук использует длинное уникальное имя, генерируемое машиной выполнения для индексации структуры данных на сервере. Машина выполнения использует протокол Netscape cookie для хранения генерируемого имени как куки/cookie на клиенте. Она не сохраняет имена и значения свойств как куки. Поэтому данная техника создаёт одну куку, в то время как клиентская техника кук создаёт отдельную куку для каждого свойства объекта client.
    Сгенерированное имя отсылается клиенту только один раз в шапке/header HTML-страницы. Вы можете получить доступ к этому имени через функцию ssjs_getClientID, описанную в разделе . Эта техника использует тот же самый cookie-файл, что и техника клиентских кук; эти виды техники отличаются тем, что информация сохраняется в cookie-файле. Протокол Netscape cookie protocol описан в книге .
    Итак, поскольку клиенту отсылается только генерируемое имя, а не реальные имена и значения свойств, не имеет значения, где на Вашей странице изменяются свойства объекта client. Это контрастирует с техникой клиентских кук.
    По умолчанию машина выполнения устанавливает период действия серверной структуры данных в 10 минут и не устанавливает срок действия кук, отправляемых клиенту. Как указано в разделе , Вы можете использовать метод expiratio объекта client для изменения срока действия и для установки периода действия куки.
    При использовании серверной куки метод client.destroy уничтожает все значения свойств объекта client.
    В общем, Netscape-куки имеют ограничения, перечисленные в разделе . Если Вы используете серверные куки, эти ограничения вряд ли будут достигнуты, так как создаётся только одна кука (содержащая индекс).
    Это быстрая техника, не имеющая встроенных ограничений на количество и размер свойств и их значений. Вы больше ограничены тем, сколько пространства будете использовать на Вашем сервере для хранения этой информации.

    Использование Списков Select

    HTML-тэг SELECT, используемый с атрибутом MULTIPLE, даёт возможность ассоциировать несколько значений с одним элементом формы. Если Вашему приложению нужны списки с возможностью выбора нескольких опций, Вы используете функцию getOptionValue для получения значений в JavaScript. Синтаксис getOptionValue таков:
    itemValue = getOptionValue(name, index)
    Здесь name это строка, специфицированная как атрибут NAME тэга SELECT, а index это порядковый индекс выбранной опции, начиная с 0. Функция getOptionValue возвращает значение выбранного элемента, как специфицировано ассоциированным тэгом OPTION.
    Функция getOptionValueCount возвращает количество опций (специфицированных тэгами OPTION) в списке выбора. Она требует только одного аргумента, строки, содержащей имя тэга SELECT.
    Например, у Вас имеется следующий элемент:

    Вы можете обработать ввод из этого select-списка таким образом:

    var i = 0;
    var howmany = getOptionValueCount("what-to-wear");

    while ( i < howmany ) {
    var optionValue =

    getOptionValue("what-to-wear", i);

    write ("
    Item #" + i + ": " + optionValue + "\n");

    i++;
    }

    Если пользователь оставил выбор по умолчанию, скрипт возвратит:
    Item #0: Jeans
    Item #1: Sweatshirt
    Item #2: Socks

    Использование URL Отладки

    Вместо Application Manager вам может больше подойти использование URL отладки приложения. Для отображения утилиты трассировки приложения в отдельном окне введите следующий URL:
    http://server.domain/appmgr/trace.html?name=appName
    Здесь appName это имя приложения. Для отображения утилиты трассировки в том же самом окне, что и окно приложения (но в отдельном кадре/фрэйме), введите URL в форме:
    http://server.domain/appmgr/debug.html?name=appName
    Вы не сможете воспользоваться двумя вышеуказанными URL, если не имеете прав для запуска Application Manager. Для удобства можно сделать закладку на URL отладки.

    Использование Внешних Функций в JavaScript

    После того как Ваше приложение зарегистрировало функцию, оно может использовать callC для её вызова. Эта функция имеет следующий синтаксис:
    callC(JSFunctionName, arguments);
    Здесь JSFunctionName это имя функции, как она была идентифицирована с помощью registerCFunction, а arguments это список разделённых запятыми аргументов внешней функции. В качестве аргументов могут использоваться любые значения JavaScript: строки, числа, булевы значения, объекты или null. Количество аргументов обязано соответствовать количеству необходимых аргументов внешней функции. Хотя Вы можете специфицировать объект JavaScript в качестве аргумента, это используется редко, поскольку объект конвертируется в строку перед передачей внешней функции.
    Эта функция возвращает строковое значение, возвращённое внешней функцией. Функция callC может возвращать только строковые значения.
    Приложение-образец jsaccall иллюстрирует использование внешних функций. Директория jsaccall содержит исходный код C (в jsaccall.c), определяющий C-функцию с именем mystuff_EchoCCallArguments. Эта функция принимает любое количество аргументов и возвращает строку, содержащую HTML с перечислением аргументов. Это пример иллюстрирует вызов функций C из приложения JavaScript и возвращаемые значения.
    Чтобы запустить jsaccall, Вы обязаны скомпилировать jsaccall.c имеющимся у Вас компилятором C. Командные строки для нескольких распространённых компиляторов даны в файле в виде комментариев.
    Следующие операторы JavaScript (взятые из jsaccall.html) регистрируют C-функцию как echoCCallArguments в JavaScript, вызывают функцию echoCCallArguments, а затем генерируют HTML на основе значения, возвращённого данной функцией.
    var isRegistered = registerCFunction("echoCCallArguments",

    "c:\\mycode\\mystuff.dll", "mystuff_EchoCCallArguments");
    if (isRegistered == true) {

    var returnValue = callC("echoCCallArguments",

    "first arg",
    42,

    true,
    "last arg");

    write(returnValue);
    }
    else {
    write("registerCFunction() returned false, "
    + "check server error log for details")
    }
    Функция echoCCallArguments создаёт результирующую строку, содержащую HTML, который выводит тип и значение каждого переданного ей аргумента JavaScript. Если registerCFunction возвращает true, вышеприведённый код генерирует такой HTML:
    argc = 4

    argv[0].tag: string; value = first arg

    argv[1].tag: double; value = 42

    argv[2].tag: boolean; value = true

    argv[3].tag: string; value = last arg

    Использование

    Вам необходимо знать, как компилятор приложений JavaScript распознаёт клиентский и серверный JavaScript в HTML-файле.
    Операторы клиентского JavaScript могут появляться в следующих ситуациях:
  • Как операторы и функции внутри тэга SCRIPT

  • При специфицировании файла как JavaScript-исходника для тэга SCRIPT

  • При специфицировании выражения JavaScript как значения HTML-атрибута

  • При включении операторов как обработчиков событий в некоторых тэгах HTML

  • О деталях см. книгу
    Клиентский JavaScript.
    .
    Операторы серверного JavaScript могут появляться в следующих ситуациях:
    Как операторы и функции внутри тэга SERVER

  • При специфицировании файла как JavaScript-исходника для компилятора приложений JavaScript

  • При специфицировании выражения JavaScript как значения или имени HTML-атрибута

  • Заметьте, что Вы не можете специфицировать оператор серверного JavaScript как обработчик события. Дополнительно см. .

    Изменение Информации Базы Данных

    Вы можете использовать обновляемый курсор для модифицирования таблицы на основе текущего ряда курсора. Чтобы запросить обновляемый курсор, добавьте дополнительный параметр true при создании курсора, как в этом примере:
    custs = connobj.cursor ("select id, name, city from customer", true)
    Чтобы курсор был обновляемым, оператор SELECT обязан быть обновляемым запросом (запросом, позволяющим производить обновление). Например, оператор не может запрашивать ряды из более чем одной таблицы или содержать условие GROUP BY, а также обычно он обязан запрашивать ключевые значения таблицы. Дополнительно о конструировании обновляемых запросов см. документацию производителя БД.
    Когда курсоры используются для внесения изменений в Вашу БД, Вы всегда должны работать в рамках явной транзакции. Вы делаете это через использование методов beginTransaction, commitTransaction и rollbackTransaction, как указано в разделе Если в таких ситуациях Вы не используете явные транзакции, Вы можете получать ошибки из Вашей БД.
    Например, Informix и Oracle возвращают сообщения об ошибке, если Вы используете курсор без явной транзакции. Oracle возвращает Error ORA-01002: fetch out of sequence; Informix возвращает Error -206: There is no current row for UPDATE/DELETE cursor.
    Как сказано в разделе , Вы не обязательно привязаны к позиции в курсоре. Исходя из этого, при внесении изменений в БД не забывайте проверять, в каком ряду Вы работаете, прежде чем изменять его.
    Также запомните, что при создании курсора указатель позиционируется перед рядом курсора. Так, чтобы обновить ряд, Вы обязаны вызвать метод next как минимум один раз для установки указателя на первый ряд таблицы. После этого Вы можете присваивать значения столбцам курсора.
    В следующем примере обновляемый курсор вычисляет премию для продавцов, выполнивших норму. Затем этой информацией обновляется БД:
    connobj.beginTransaction ();emps = connobj.cursor(
    "select * from employees where dept='sales'", true);
    // Прежде чем продолжить, убедитесь, что курсор действительно был возвращён
    // и не было ошибки БД.


    if ( emps && (connobj.majorErrorCode() == 0) ) {

    // Производится итерация по рядам курсора с обновлением информации на базе // return-значения функции metQuota.

    while ( emps.next() ) {

    if (metQuota (request.quota, emps.sold)) {

    emps.bonus = computeBonus (emps.sold);

    }
    else emps.bonus = 0;

    emps.updateRow ("employees");
    }

    // После выполнения - закрывается курсор и подтверждается транзакция.

    emps.close();
    connobj.commitTransaction();
    }
    else {

    // Если курсор для работы отсутствовал, транзакция откатывается.

    connobj.rollbackTransaction();
    }

    Этот пример создаёт обновляемый курсор для всех employees/служащих департамента Sales. Производится итерация по рядам курсора через использование определяемой пользователем функции JavaScript metQuota, для того чтобы определить, выполнил ли служащий норму. Эта функция использует значение свойства quota объекта request (возможно, установленное в форме на клиентской странице) и столбец sold курсора для выполнения этого определения. Код затем устанавливает соответствующую премию и вызывает updateRow

    для модифицирования таблицы employees. Когда пройдены все ряды курсора, подтверждается транзакция. Если вызов метода cursor не вернул никакого курсора, транзакция откатывается.

    Помимо метода updateRow, Вы можете использовать методы insertRow и deleteRow для вставки нового ряда или удаления текущего. При использовании deleteRow не нужно присваивать никакого значения, поскольку этот метод просто удаляет весь ряд.

    Если Вы используете insertRow, значения, присваиваемые столбцам, используются для нового ряда. Если перед этим Вы вызвали метод next курсора, то текущие значения в ряду используются для столбцов без присвоенных значений; иначе столбцы будут иметь значения null. Также, если некоторые столбцы таблицы не вошли в курсор, insertRow вставляет null в эти столбцы. Место расположения вставляемого ряда зависит от библиотеки производителя БД. Если Вам нужен доступ к ряду после вызова метода insertRow, Вы обязаны сначала закрыть имеющийся курсор, а затем открыть новый.

    ПРИМЕЧАНИЕ:


    В DB2 имеется тип данных Time. JavaScript не имеет соответствующего типа данных. Поэтому Вы не можете обновлять ряды значениями, использующими тип данных DB2 Time.

    Изменения в JavaScript Application Manager

    Функциональность менеджера JavaScript Application Manager не изменилась в Enterprise Server 4.0 по сравнению с Enterprise Server 3.x. Однако он теперь использует ту же новую схему цветов, что и Server Manager в Enteprise Server 4.0, и имеет некоторые изменения внешнего вида.
    Изменения в JavaScript Application Manager
    JavaScript Application Manager теперь имеет три вкладки:
  • Applications


  • Слева - список установленных приложений и кнопки Start, Stop, Restart, Run, Debug, Modify и Remove. Правая панель содержит информацию о приложении, выбранном в списке приложений. Если Вы щёлкните мышью кнопку Modify, в правой панели отобразятся поля, которые дают Вам возможность модифицировать выбранное приложение.
  • Add Application

    Добавить новое приложение.
  • Preferences

    Специфицировать значения по умолчанию при добавлении нового приложения.

  • Хотя названия и внешний вид вкладок и кнопок в JavaScript Application Manager в Enterprise Server 4.0 слегка отличается от Enterprise Server 3.6, их функциональность не изменилась.

    Ядро JavaScript

    Клиентский и серверный JavaScript имеют следующие общие элементы:
  • Ключевые слова

  • Синтаксис операторов и грамматику

  • Правила написания выражений, переменных и литералов

  • Лежащую в основе объектную модель (хотя клиентский и серверный JavaScript имеют разные предопределённые объекты)

  • Предопределённые объекты и функции, такие как Array, Date и Math


  • Ядро, Клиентский и Серверный JavaScript

    Компоненты JavaScript показаны на рисунке:

    Рисунок 1.1 Язык JavaScript

    Ядро, Клиентский и Серверный JavaScript
    В следующем разделе разбирается работа JavaScript на стороне клиента и на сервере.

    JavaScript и Java

    JavaScript и Java напоминают друг друга, но имеют и фундаментальные отличия. JavaScript не имеет статической типизации и строгой проверки типов Java. JavaScript поддерживает большую часть синтаксиса выражений Java и базовые конструкции управления потоком.
    В отличие от системы времени компиляции Java, построенной на объявлениях, JavaScript поддерживает систему времени выполнения, основанную на небольшом количестве типов данных: числовых, Булевых и строковых. JavaScript имеет объектную модель на базе прототипов вместо более общей объектной модели на базе классов. Модель на базе прототипов предоставляет возможность динамического наследования; то есть, то, что наследуется, может отличаться для разных объектов. JavaScript также поддерживает функции без специальных требований объявления. Функции могут быть свойствами объектов, исполняемыми как нетипизированные методы.
    JavaScript это язык, свободный по форме, по сравнению с Java. Вы не должны объявлять все переменные, классы и методы. Вы не должны учитывать, являются ли методы public, private или protected, и не обязаны реализовывать интерфейсы. Return-типы переменных, параметров и функций не типизированы явно.
    Java это язык на базе классов, разработанный для быстрого выполнения и строгой типизации. Строгая типизация означает, к примеру, что Вы не можете привести/cast целое число Java (integer) к ссылке на объект или получить доступ к private-памяти, нарушая байт-коды Java. Модель Java на базе классов означает, что программы состоят исключительно из классов и их методов. Наследование классов в Java и строгая типизация обычно требуют тесно выстроенной иерархий объектов. Эти требования делают программирование на Java более сложным, чем авторизация на JavaScript.
    В противоположность этому, JavaScript ведёт своё начало от небольших динамически типизированных языков, таких как HyperTalk и dBASE. Эти языки сценариев предоставляют утилиты программирования для более широкой аудитории, поскольку имеют облегчённый синтаксис, специализированную встроенную функциональность и минимальные требования при создании объектов.

    JavaScript Java


    Интерпретируется (не компилируется) клиентом.


    Скомпилированные байт-коды, загруженные с сервера, выполняются на клиенте.


    Объектно-ориентированный. Нет отличий между типами объектов. Наследование осуществляется через механизм прототипов, а свойства и методы могут добавляться к объекту динамически.


    На базе классов. Объекты делятся на классы и экземпляры, наследующие по всей цепи иерархии классов. Классы и экземпляры не могут иметь свойства и методы, добавляемые динамически.


    Коды интегрированы и внедрены в HTML.


    Аплеты отличаются от HTML (доступ к ним осуществляется из HTML-страниц).


    Типы переменных не объявляются (динамическая типизация).


    Типы переменных обязаны быть объявлены (статическая типизация).


    Не может автоматически записывать на жёсткий диск.


    Не может автоматически записывать на жёсткий диск.

    JavaScript и Спецификация ECMA

    Netscape изобрела JavaScript, и JavaScript был впервые использован в браузерах Netscape. Одновременно Netscape работает с (European Computer Manufacturers Association) для создания стандартизованного международного языка программирования на базе ядра JavaScript. ECMA это международная ассоциация стандартов в области систем информации и коммуникаций. Эта стандартизованная версия JavaScript, называемая ECMAScript, ведёт себя совершенно одинаково во всех приложениях, поддерживающих этот стандарт. Компании могут использовать этот открытый стандартный язык для создания своих реализаций JavaScript. Первая версия стандарта ECMA документирована в спецификации ECMA-262.
    Стандарт ECMA-262 одобрен также (International Organization for Standards) как ISO-16262. Вы можете найти на Netscape DevEdge Online. Вы также можете найти эту на сайте ECMA. Спецификация ECMA не описывает Document Object Model (DOM), которая стандартизуется консорциумом . DOM определяет способ, которым объекты HTML-документа экспонируются в скрипте.

    JavaScript и Технология ECMA

    Спецификация ECMA использует терминологию и синтаксис, которые могут быть незнакомы программистам JavaScript. Хотя описание языка может отличаться в ECMA, сам язык остаётся тем же самым. JavaScript поддерживает всю функциональность, данную в спецификации ECMA.
    Документация по JavaScript описывает аспекты языка, необходимые программисту на JavaScript. Например:
  • Объект global не обсуждается в документации JavaScript, поскольку Вы не используете его явно. Методы и свойства объекта global, используемого Вами, обсуждаются в документации JavaScript, но называются функциями и свойствами верхнего уровня.

  • Конструктор без параметров (zero-argument) с объектами Number и String не обсуждается в документации JavaScript, поскольку то, что генерируется, используется мало. Number -конструктор без аргументов возвращает +0, а String -конструктор без аргументов возвращает "" (пустую строку).


  • Этапы Использования Хранимых Процедур

    После установки соединения с БД этапы использования хранимой процедуры в Вашем приложении несколько различаются для разных БД:
    (Только DB2) Хранимая процедура регистрируется в соответствующих системных таблицах. (Это выполняется вне JavaScript.)

  • (DB2, ODBC и Sybase) Определяется прототип для Вашей хранимой процедуры.

  • (Все БД) Выполняется хранимая процедура.

  • (Все БД) Создаётся resultSet -объект и получаются данные из этого объекта.

  • (DB2, ODBC и Sybase) Выполнение завершается доступом к return-значению.

  • (DB2, ODBC, Oracle и Sybase) Выполнение завершается получением параметров вывода.

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

    Как Работает Hello World?

    Это приложение демонстрирует две важные вещи: обслуживание различных клиентских статусов нескольких клиентов и обслуживание существующего статуса приложения. Оно выполняет следующие функции:
    Выводит IP-адрес клиента, выполнившего запрос.
  • Выводит имена, введённые ранее, и форму для ввода имени пользователя.

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

  • При первом посещении страницы пользователем значения обоих имён не определены. Количество предыдущих посещений пользователя равно 0; общее количество посещений также равно 0.
    Введите своё имя и нажмите Enter. Страница теперь показывает введённое имя и текст "This time you are." Оба числа посещений увеличиваются на 1. Эта акция иллюстрирует простейшую обработку данных формы. Введите другое имя и нажмите Enter. Страница теперь показывает новое имя и текст "This time you are", а предыдущее имя с - текстом "Last time you were." И вновь оба числа посещений увеличиваются.
    Если Вы выполните доступ к приложению из другого экземпляра Navigator'а (или с другого компьютера), страница покажет общее число посещений и количество посещений каждого экземпляра Navigator'а, а не только одного данного экземпляра.

    Классы и Объекты

    Для поддержания различных задач, выполняемых на каждой стороне, JavaScript имеет классы и предопределённые объекты, которые работают на клиенте, но не на сервере, и другие классы и предопределённые объекты, которые работают на сервере, но не на клиенте.
    Важно!
    Названия этих объектов зарезервированы для JavaScript. Не создавайте Ваши собственные объекты, используя эти имена.
    Ядро языка JavaScript предоставляет классы, описанные в следующей таблице. Детальную информацию обо всех этих объектах см. в книге
    .

    КлассОписание
    Array
    Массив.
    Boolean
    Булево значение.
    Date
    Дата.
    Function
    Специфицирует строку кода JavaScript, компилируемую как функция.
    Math
    Предоставляет основные математические константы и функции; например, свойство PI содержит значение pi.
    Number
    Примитивные числовые значения.
    Object
    Базовая функциональность всех объектов JavaScript.
    Packages
    Пакет Java в JavaScript. используется вместе с LiveConnect.
    String
    Строка JavaScript.

    Серверный JavaScript включает классы ядра, но не классы клиентского JavaScript. Серверный JavaScript имеет свой набор дополнительных классов для поддержки необходимой функциональности, как показано в следующей таблице.
    КлассОписание
    Connection
    Одиночное соединение с БД из пула соединений. (См. ).
    Cursor
    Курсор БД. (См. ).
    DbPool
    Пул соединений с базами данных. (См. ).
    Stproc
    Хранимая процедура БД. (См. ).
    Resultset
    Представляет информацию, возвращаемую хранимой процедурой БД. (См. .)
    File
    Предоставляет доступ к файловой системе сервера. (См. .)
    Lock
    Предоставляет функциональность для безопасного совместного использования/sharing данных запросами, клиентами и приложениями. (См. .)
    SendMail
    Предоставляет функциональность для отправки электронной почты из вашего приложения JavaScript. (См. .)

    Кроме того, серверный JavaScript имеет предопределённые объекты, описанные в следующей таблице. Эти объекты доступны для каждого HTTP-запроса. Вы не можете создать дополнительные экземпляры какого-либо из этих объектов.

    ОбъектОписание
    database

    Соединение с базой данных. (См. )
    client

    Инкапсулирует информацию о паре клиент/приложение, позволяя хранить эту информацию дольше, чем в течение одного HTTP-запроса. (См. )
    project

    Инкапсулирует информацию о приложении, которая хранится, пока приложение не прекратит работу на сервере. (См. .)
    request

    Инкапсулирует информацию об отдельном HTTP-запросе. (См. .)
    server

    Инкапсулирует глобальную информацию о сервере, которая хранится, пока сервер не остановится. (См. .)

    Клиентская Техника

    Есть два вида клиентской техники:
  • Клиентские куки
  • Клиентское кодирование URL

  • Сравнение этих видов техники см. в разделе .
    Когда приложение использует клиентские виды техники, машина выполнения кодирует свойства объекта client в ответ на клиентский запрос в шапке/header ответа (для клиентской куки) или в URLs в теле ответа (для клиентского кодирования URL).
    Поскольку реальные имена и значения свойств пересылаются между клиентом и сервером, рестарт сервера не вызывает потери клиентской информации. Однако отправка этой информации вызывает увеличение сетевого трафика.

    Клиентский JavaScript

    Web-браузеры, такие как Navigator (2.0 и более поздние версии) могут интерпретировать операторы клиентского JavaScript, внедрённые в HTML-страницу. Когда браузер (или клиент) запрашивает такую страницу, сервер высылает клиенту по сети полное содержимое документа, включая HTML и операторы JavaScript. Браузер читает страницу сверху вниз, отображая результат работы HTML и выполняя операторы JavaScript по мере их обнаружения. Этот процесс, проиллюстрированный на рисунке, производит результат, который видит пользователь.

    Рисунок 1.2Клиентский JavaScript

    Клиентский JavaScript
    Операторы клиентского JavaScript, встроенного в HTML-страницу, могут реагировать на пользовательские события, такие как щелчок мыши, ввод данных в форму и навигация по страницам. Например, Вы можете написать функцию JavaScript для проверки ввода пользователем правильной информации в форму, запрашивающую телефонный номер или zip-код. Без передачи по сети внедрённый JavaScript на HTML-странице может проверить введённые данные и вывести диалоговое окно, если пользователь ввёл неверные данные.
    Разные версии JavaScript работают со специфическими версиями Navigator'а. Например, JavaScript 1.2 работает с Navigator 4.0. Некоторые возможности JavaScript 1.2 недоступны в JavaScript 1.1 и поэтому недоступны в Navigator 3.0. Информацию о версиях JavaScript и Navigator см. в разделе .

    Кодирование Информации в URL

    Вы можете вручную кодировать свойства объекта request в URL, по которому выполняется доступ к странице Вашего приложения. При создании URL используется следующий синтаксис:
    URL?varName1=value1[&varName2=value2...]
    Здесь URL это базовый URL, каждое varNameN это имя свойства, каждое valueN это соответствующее свойству значение (с мнемониками специальных символов). В этой схеме после базового URL идёт знак вопроса (?), после которого, в свою очередь, идут пары имён свойств и их значений. Каждая пара отделяется амперсандом (&). Когда машина выполнения на сервере получает результирующий URL в качестве клиентского запроса, она создаёт свойство объекта request под названием varNameN для каждой переменной.
    Например, следующий HTML определяет гиперссылку на страницу, инстанциирующую свойства объекта request i и j в 1 и 2, соответственно. Операторы JavaScript в refpage.html могут затем обратиться к эти переменным request.i и request.j.
    Click Here
    Вместо использования статической URL-строки, как в предыдущем примере, Вы можете использовать операторы серверного или клиентского JavaScript для динамической генерации URL, кодирующего значения свойств. Например, Ваше приложение может включать страницу:






    Click here to submit a value.



    В данном случае, если пользователь щёлкнет на ссылке, машина выполнения на клиенте запустит на выполнение обработчик события onClick. Этот обработчик устанавливает часть поиска из URL в ссылке в какую-нибудь строку, возвращённую функцией compute. Когда машина выполнения на сервере получит этот запрос, она создаст свойство num объекта request и установит его значение в 25.

    В качестве второго примера Вы можете добавить свойства объекта request в URL, созданный в серверном скрипте. Это особенно применимо, если Вы перенаправляете клиентский запрос на новую страницу. Чтобы добавить свойства объекта request в серверный скрипт, Вы можете использовать такой оператор:

    Например, в Hangman вместо

    можно записать

    write("
    write(client.num_misses);
    write(".gif\">");

    Обратите внимание, что обратная наклонная черта (backslash) даёт возможность ввести знак кавычки внутри литеральной строки. Хотя результирующий HTML - тот же самый, в этом случае обратные кавычки предпочтительнее, поскольку исходник легче читать и редактировать.

    Когда Можно Использовать Результирующие Наборы

    Объект resultSet не является бесконечно действующим. Вообще, когда хранимая процедура стартует, не допускается никакое взаимодействие между клиентом БД и сервером БД, пока хранимая процедура не завершит выполнение. Есть три ситуации, когда результирующий набор является недействующим:
  • Если Вы создаёте результирующий набор как часть транзакции, Вы обязаны закончить использование результирующего набора в течение выполнения этой транзакции. Если Вы подтвердили транзакцию или выполнили её откат, Вы не сможете получать данные из результирующего набора и не сможете получить дополнительные результирующие наборы. Например, следующий код не допускается:
  • database.beginTransaction();
    spobj = database.storedProc("getcusts");

    resobj = spobj.resultSet();
    database.commitTransaction();
    // Неверно! Результирующий набор больше не действует!

    col1 = resobj[0];

  • Для Sybase, ODBC и DB2 Вы обязаны запросить resultSet -объекты до вызова методов returnValue или outParameters объекта хранимой процедуры. Если Вы вызвали один из этих методов, Вы не сможете больше получать данные из результирующего набора и не сможете получить дополнительные результирующие наборы. См. о работе этих методов раздел .
  • spobj = database.storedProc("getcusts");

    resobj = spobj.resultSet();
    retval = spobj.returnValue();
    // Неверно! Результирующий набор больше не действует!

    col1 = resobj[0];

  • Для Sybase Вы обязаны запросить resultSet -объекты до вызова методов cursor или SQLTable ассоциированного соединения. Как только Вы вызовете cursor или SQLTable, результирующий набор станет недоступен. Например, следующий код неверен:
  • spobj = database.storedProc("getcusts");
    resobj = spobj.resultSet();

    curobj = database.cursor ("select * from orders");
    // Неверно! Результирующий набор больше не доступен!

    col1 = resobj[0];

  • Для ODBC соблюдаются несколько иные ограничения. Вы также обязаны работать с resultSet -объектами до вызова методов cursor или SQLTable ассоциированного соединения. В ODBC, если Вы получаете курсор, выполняете доступ к результирующему набору, а затем используете курсор, Cursor -объект становится недоступным. Например, следующий код неверен:
  • spbobj = database.storedProc("getcusts");
    resobj = spobj.resulSet();

    curobj = database.cursor ("select * from orders");
    col1 = resobj[0]; // Неверно! Курсор больше не доступен.

    curobj.next();

    Компиляция Приложения

    Вы компилируете приложение JavaScript, используя компилятор приложений JavaScript, jsac. Компилятор создаёт web-файл из исходных файлов на языках HTML и JavaScript.
    Примечание

    Netscape Enterprise Server 4.0 поддерживает компилятор JavaScript Application Compiler версии 24.13. Заметьте, что приложение, скомпилированное с использованием "=" в качестве операции Equal, не сможет использовать новый компилятор. Вы обязаны использовать "==" в качестве операции Equal (==).
    Для облегчения доступа к компилятору Вам может понадобиться добавить директорию, в которой он установлен, в переменную окружения PATH. От том, как это сделать, см. раздел в
    Вам нужно также добавить директорию /bin/httpd/lib в LD_LIBRARY_PATH (или LIBPATH, или SHLIB_PATH на Unix-платформах), либо /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, smallintinteger
    decimal, doubledouble
    date, time, timestamp Date
    blobBlob

    В следующей таблице дана конвертация БД Informix.

    Тип Данных Informix
    Тип Данных JavaScript
    char, nchar, text, varchar, nvarcharstring
    decimal(p,s), double precision, float, integer, money(p,s), serial, smallfloat, smallintnumber
    date, datetimeDate
    byteBlob
    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)numberdateDateraw(n), long rawBlob
    В следующей таблице показана конвертация, выполняемая машиной выполнения 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

    Менеджер Приложений JavaScript. Обзор.

    Рисунок 3.3 Application Manager в Enterprise Server 4.0

    Менеджер Приложений JavaScript. Обзор.
    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 ("" +
    "" +
    "");
    }
    write ("
    " + custs.title + "" + custs.rentalDate + "" + custs.dueDate + "
    ");
    // Всегда закрывайте курсоры по окончании работы!

    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 это директория, в которой Вы установили сервер.
    В таблице перечислены приложения-образцы.
    Базовые понятия LiveWire Database Service dbadmin LiveConnect Другие приложения
    worldПриложение "Hello World".
    hangman"Виселица".
    cipherУгадай цифру.
    Простой интерактивный SQL-доступ с использованием LiveWire.
    Если Вы имеете ограниченный доступ к Application Manager, это приложение также защищено именем и паролем администратора сервера.
    videoappПриложение видео-магазин, использующее реляционную БД видеоклипов.
    oldvideoАльтернативная версия видео-магазина.
    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-клиент

    О Сервисе 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


    ID:

    write("" +

    project.lastID + "
    ");





    При доступе к этой странице машина выполнения выполняет на сервере код, ассоциированный с тэгами SERVER. (Этот код выделен жирным шрифтом.) Если ID нового потребителя 42, сервер высылает клиенту для отображения такую HTML-страницу:


    Add New Customer





    Add a New Customer


    Note: All fields are required for the new customer



    ID:


    42






    Обзор Процессов Времени Прогона (Выполнения)

    После того как Вы установили и стартовали приложение JavaScript, пользователь может получить к нему доступ.

    Базовые процедуры таковы:
  • Пользователь выполняет доступ к приложению по его URL в web-браузере, таком как Netscape Communicator. Браузер отправляет клиентский запрос страницы приложения на сервер.

  • Если это запрос к странице с URL приложения, машина выполнения JavaScript, запущенная на сервере, находит информацию в web-файле, соответствующем этому URL. О деталях этого процесса и о том, что происходит на этом и на последующих двух этапах, см. в разделе .

  • Машина времени выполнения конструирует HTML-страницу для отправки клиенту. Она выполняет байт-коды, ассоциированные с тэгами SERVER, из исходного кода HTML, создавая HTML-страницу на основе этих байт-кодов и иного HTML, имеющегося в оригинале. О том, как влиять на процесс конструирования страницы, см. в разделе .

  • Машина выполнения высылает новую HTML-страницу (которая может содержать операторы клиентского JavaScript) клиенту.

  • Машина выполнения JavaScript внутри web-браузера интерпретирует любые операторы клиентского JavaScript, форматирует вывод HTML и выводит результат пользователю.

  • иллюстрирует это процесс.
    Рисунок 5.1Процессинг запроса JavaScript-страницы

    Обзор Процессов Времени Прогона (Выполнения)
    Конечно, пользователь обязан иметь Netscape Navigator (или иной браузер с возможностью выполнения JavaScript), чтобы клиент мог интерпретировать операторы клиентского JavaScript. Аналогично, если Вы создаёте страницу, содержащую серверный JavaScript, он должен быть установлен на Netscape-сервере, чтобы нормально функционировать.
    Например, предположим, клиент запрашивает страницу с таким исходным кодом:

    Add New Customer






    if ( project.lock() ) {
    project.lastID = 1 + project.lastID;

    client.customerID = project.lastID;
    project.unlock();
    }

    Очистка Буфера Вывода

    Для повышения производительности, JavaScript буферизует конструируемую им HTML-страницу. Функция flush сразу высылает данные из внутреннего буфера клиенту. Если Вы явно не вызываете функцию flush, JavaScript высылает данные клиенту после создания каждых 64KB содержимого конструируемой HTML-страницы.
    Не путайте функцию flush с методом flush класса File. (Об использовании класса File для ввода и вывода в файл см. ).
    Вы можете использовать flush для управления временем переноса данных клиенту. Например, Вы можете очищать буфер до операции, создающей задержку/delay, такой как запрос к базе данных. Также, если запрос к БД запрашивает большое количество рядов, очистка буфера каждый раз после получения нескольких рядов предотвращает паузы при отображении данных.
    ПРИМЕЧАНИЕ:
    Если Вы используете клиентские куки для обслуживания свойств объекта client, Вы обязаны делать все изменения объекта client до очистки буфера. Дополнительно см. .
    Следующий фрагмент кода показывает, как используется flush. Предположим, Ваше приложение должно выполнить некоторые действия с каждым потребителем/customer в Вашей БД потребителей. Если потребителей много, процесс может затянуться. Поэтому, для того чтобы пользователь не ждал у застывшего экрана, Ваше приложение может высылать вывод клиенту до начала обработки и затем вновь - после конца обработки каждого ряда. Для этого Вы должны использовать примерно такой код:
    flush();
    conn.beginTransaction();

    cursor = conn.cursor ("SELECT * FROM CUSTOMER", true);
    while ( cursor.next() ) {

    // ... обработка ряда ...
    flush();
    }

    conn.commitTransaction();
    cursor.close();

    ODBC Data Source Names/Имена Источников Данных (только NT)

    Могут быть созданы два типа источников данных:
  • System/Системное DSN: Если вы используете системное DSN, web-сервер обязан стартовать в бюджете System.
  • User/Пользовательское DSN: Если вы используете пользовательское DSN, web-сервер обязан стартовать в соответствующем пользовательском бюджете NT (user account).

  • Источник данных описывает параметры соединения для каждой БД, необходимые для ODBC connectivity. Источник данных определяется чрез использование ODBC-администратора. Если ODBC установлен, администратор также устанавливается. Каждый ODBC-драйвер требует различной информации для определения источника данных.

    ODBC

    Все платформы: О возможностях и об используемых ODBC-драйверах см.
    Вам необходимо иметь соответствующие ODBC-драйверы для БД, с которой Вы устанавливаете соединение. Также необходимо иметь дополнительные файлы ODBC-соединений/connectivity.
    Большинство программных продуктов, предоставляющие ODBC connectivity, поддерживают ODBC-драйвер или драйверы и ODBC connectivity.
    Только для NT: В настоящее время Netscape сертифицирован с ODBC Manager версии 2.5. Если у вас имеется доступ к ODBC-драйверу, но не к файлам ODBC connectivity, Вы можете получить их в MS ODBC SDK. Чтобы получить обновлённые файлы для Access, Foxpro и Excel, Вам может понадобиться патч WX1350 от Microsoft.
    Только для Unix: Для ODBC на Unix вы можете использовать драйвер от Visigenic либо от OpenLink. Если Вы используете драйвер от Visigenic, следуйте инструкциям раздела Если Вы используете драйвер от OpenLink, следуйте инструкциям раздела

    Однопоточные и Многопоточные Базы Данных

    LiveWire поддерживает многопоточный доступ к БД. То есть она поддерживает наличие более чем одного потока доступа к одной БД в единицу времени. Отсюда ясно, для чего нужен пул соединений с более чем одним соединением. Однако библиотеки БД некоторых производителей не являются многопоточными. Для таких БД не имеет значения, сколько соединений имеется в Вашем пуле, так как только одно соединение может устанавливаться с БД в единицу времени.
    В этой таблице дан список клиентских библиотек баз данных, которые являются многопоточными на указанных платформах.

    SybaseInformixOracle
    DB2ODBC
    NTЕстьЕстьЕстьЕстьЕсть
    Sun SolarisЕстьЕстьЕстьНетНет
    HP-UXЕстьЕстьНетНетНет
    IBM AIXЕстьЕстьНетЕстьНет
    SGI IRIXНетНетНетНе поддерживаетсяНет
    Digital UnixЕстьЕстьНетНе поддерживаетсяНе поддерживается

    1
    Все многопоточные тесты для ODBC были сделаны на MS SQL Server. Если Вы используете другой драйвер ODBC, узнайте у производителя, является ли драйвер многопоточным.


    Окружение (Рабочая Среда)

    Возможности LiveConnect ядра языка JavaScript работают на сервере иначе, чем на клиенте. См. дополнительно .
    JavaScript предоставляет дополнительную функциональность без использования объектов. Вы получаете доступ к этой функциональности через функции, не ассоциированные с каким-либо объектом (глобальные функции). Ядро языка JavaScript имеет глобальные функции, описанные в следующей таблице (также как и другие функции, описанные в документации Ядра JavaScript).

    ФункцияОписание
    escape
    Возвращает 16-ричный код аргумента - символа из набора символов ISO Latin-1; используется при создании строк для добавления в URL.
    unescape
    Возвращает ASCII-строку для специфицированного значения; используется при разборе строки, добавленной в URL.
    isNaN
    Вычисляет аргумент для определения не является ли он "неЧислом".
    parseFloat
    Разбирает аргумент-строку и возвращает число с плавающей точкой.
    parseInt
    Разбирает аргумент-строку и возвращает целое число.

    Серверный JavaScript добавляет глобальные функции, описанные в следующей таблице.

    ФункцияОписание
    write
    Добавляет операторы к генерируемой клиентской HTML-странице. (См. .)
    flush
    Очищает буфер вывода. (См. .)
    redirect
    Перенаправляет клиента по специфицированному URL. (См. .)
    getOptionValue
    Получает значения отдельных опций в элементе HTML-формы SELECT. (См. .)
    getOptionValueCount
    Получает количество опций в элементе HTML-формы SELECT. (См. .)
    debug
    Выводит значения выражений в окне (фрэйме) трассировки. (См. .)
    addClient
    Присоединяет клиентскую информацию к URL. (См. .)
    registerCFunction
    Регистрирует внешнюю функцию для использования в серверном JavaScript. (См. .)
    callC
    Вызывает внешнюю функцию. (См. .)
    deleteResponseHeader
    Удаляет информацию из "шапки" ответа, высылаемого клиенту. (См. .)
    addResponseHeader
    Добавляет новую информацию в "шапку" ответа, высылаемого клиенту. (См. .)
    ssjs_getClientID
    Возвращает идентификатор для client -объекта, используемый при некоторых видах клиентской техники JavaScript. (См. .)
    ssjs_generateClientID
    Возвращает идентификатор, который Вы можете использовать для уникального специфицирования объекта client. (См. .)
    ssjs_getCGIVariable
    Возвращает значение специфицированной переменной окружения CGI. (См. .)


    OpenLink ODBC-Драйвер (только Solaris)

    Установите брокер запросов OpenLink Workgroup Edition ODBC Driver на сервер БД. Он должен быть запущен, до того как Вы сможете соединиться с БД с использованием агента запросов OpenLink.
    Установите агента запросов (request agent) в клиенте OpenLink Generic ODBC версии 1.5 на клиентской машине БД.
    Переименуйте или скопируйте файл драйвера менеджера агента запросов из libiodbc.so в libodbc.so в директории $ODBCDIR/lib, где $ODBCDIR это директория, в которой установлен ODBC.
    Когда Вы устанавливаете Ваш сервер, Вы делаете так, чтобы он запускался как некоторый пользователь: root, nobody или конкретный пользователь сервера. Выбранный Вами пользователь должен иметь домашнюю директорию, которую, возможно, понадобится создать. Например, по умолчанию домашняя директория для пользователя nobody на Irix это /dev/null. Если Вы устанавливаете Ваш сервер на Irix как nobody, Вы обязаны создать для пользователя nobody другую домашнюю директорию.
    В этой домашней директории Вы обязаны иметь файл .odbc.ini. Например, если сервер запускается как root, этот файл находится в директории (/).
    Установите следующие переменные окружения:
    LD_LIBRARY_PATH
    (Solaris и Irix) Добавляет размещение ODBC-библиотек к данной переменной.
    UDBCINI
    Специфицирует местонахождение файла .odbc.ini.


    Определение Прототипа для Хранимой Процедуры

    Этот этап относится только к пользовательским и системным хранимым процедурам DB2, ODBC и Sybase. Вам не нужно определять прототип хранимых процедур БД Oracle или Informix.
    Для DB2, ODBC и Sybase программа не может определить в процессе выполнения, предназначен определённый параметр для ввода, вывода, или для того и другого. Соответственно, после того как Вы подключились к БД, Вы обязаны создать прототип, предоставляющий информацию о хранимой процедуре, которую Вы хотите использовать, через метод storedProcArgs объекта database или DbPool.
    Вам нужно использовать по одному прототипу для каждой хранимой процедуры Вашего приложения. Программа игнорирует дополнительные прототипы для одной и той же процедуры.
    В прототипе Вы предоставляете имя хранимой процедуры и тип каждого из её параметров. Параметр обязан быть: для ввода/input (IN), вывода/output (OUT), а для ввода и вывода - (INOUT).

    Например, чтобы создать прототип для хранимой процедуры newhire, имеющей два параметра ввода и один параметр вывода, можно использовать такой вызов метода:
    poolobj.storedProcArgs("newhire", "IN", "IN", "OUT");

    Oracle

    Чтобы использовать сервер Oracle, Вы обязаны иметь Netscape Enterprise Server. Вы не можете получить доступ к Oracle из Netscape FastTrack Server.
    Если БД и web-сервер находятся на разных машинах, следуйте инструкциям раздела
    Если БД и web-сервер находятся на одной машине, следуйте инструкциям раздела
    Только для Unix: Убедитесь, что Вы можете соединиться с Вашей БД Oracle через SQL*Net. Если Вы закончили инсталяцию, Вы можете использовать loopback-тест для проверки корректности соединения. Например, из sqlplus Вы можете попытаться соединиться с Вашей БД с помощью следующей команды:
    connect username/password@service_name
    Или из командной строки Unix:
    sqlplus username/password@service_name
    В этих командах Вы используете service_name из Вашего файла tnsnames.ora.

    Прежде чем использовать нижеуказанные инструкции, Вы обязаны сконфигурировать Ваш Oracle-клиент, как указано в разделе Помимо этого, Ваш клиент обязан быть сконфигурирован для запуска утилит Oracle. Чтобы запускать SQL Plus, Вам может понадобиться установить переменную окружения ORACLE_SID.
    SQL-файлы для создания видео-БД в Oracle, находятся в двух директориях:
    $NSHOME\js\samples\videoapp\ora
    $NSHOME\js\samples\oldvideo\ora
    И в Unix, и в NT: стартуйте SQL Plus. Из промпта SQL> введите такую команду:Start $NSHOME\js\samples\videoapp\ora\ora_video.sql
    Вы можете также запустить этот скрипт из директории oldvideo. Этот SQL-скрипт не создаёт новую БД. Он создаёт таблицы Oracle в текущем экземпляре.

  • В Unix: запустите скрипт-файл ora_load для загрузки видео-таблиц с данными. В NT: запустите пакетный файл ora_load.bat для загрузки видео-таблиц с данными. Вы обязаны отредактировать соответствующий файл для подключения к Вашему серверу; инструкции об этом содержатся в файле.

  • Теперь можно запускать приложение, сделав изменения, описанные в разделе .


  • Основные Этапы Создания Приложения

    Обычно HTML статичен: после того как Вы написали HTML-страницу, её содержимое фиксируется. Фиксированное содержимое пересылается с сервера клиенту, когда клиент выполняет доступ к странице по её URL. С помощью JavaScript Вы можете создавать HTML-страницы, которые могут изменяться вслед за изменением данных или в ответ на действия пользователя. На показана базовая процедура создания и запуска приложения JavaScript.
    Рисунок 3.1 Создание и Запуск Приложения JavaScript

    Основные Этапы Создания Приложения
    Для создания приложения JavaScript Вы должны выполнить следующие шаги:
    Создать исходные файлы. Исходные файлы могут быть HTML-файлами с внедрённым JavaScript, файлами, содержащими только JavaScript, или исходными файлами на Java. (См. .)

    Заметьте, что Виртуальная Машина JavaScript (VM), используемая в Netscape Enterprise Server 4.0, реализует значительные улучшения в процессинге локальных переменных (то есть переменных, объявленных внутри функций), по сравнению с NES 3.6. Отсюда следует, что нужно минимизировать использование глобальных переменных (то есть тех, которые объявлены между тэгами и ) и переписать приложения так, чтобы максимально использовать функции. Это значительно увеличит скорость работы приложения.

  • Построить приложение с использованием компилятора приложений JavaScript для создания исполняемого байт-кода (файла .web). (См. .) Скомпилировать исходные файлы Java в файлы классов.

  • Опубликовать web-файл, все необходимые файлы HTML, изображений и клиентского JavaScript и откомпилированные файлы Java-классов в соответствующие директории на сервере. Вы можете использовать Netscape Web Publisher для публикации Ваших файлов, как описано в книге Web Publisher User's Guide.

  • Установить приложение в первый раз (см. ) с помощью Менеджера Приложений JavaScript. Вы можете также использовать Менеджер Приложений для рестарта приложения после его перестроения/rebuilding (см. ). Инсталяция или рестарт приложения заставляют машину выполнения JavaScript запустить это приложение на выполнение.


    После инсталяции приложения Вам может потребоваться защитить его. См. раздел . Вам не нужно рестартовать приложение после его начальной инсталяции.


  • Запустить приложение, щёлкнув Run в Менеджере Приложений или загрузив URL приложения в браузер. (См. и .) Например, чтобы запустить Hello World, загрузите в браузер http://server.domain/world/. Вы можете выполнить также отладку приложения, щёлкнув Debug в Менеджере Приложений. (См. .)


  • После того как Вы завершили разработку и тестирование Вашего приложения, Вам нужно будет опубликовать его, чтобы сделать доступным для пользователей. Процесс публикации обычно включает в себя инсталяцию приложения на конечном сервере и изменение прав доступа. (См. .)


  • Прежде чем Вы сможете разрабатывать приложения на JavaScript, Вам нужно будет запустить машину выполнения на сервере и, возможно, защитить Менеджер Приложений JavaScript от неавторизованного доступа. Дополнительно см. разделы и .

    Открытие и Закрытие Файла

    После создания File -объекта Вы можете использовать метод open для открытия файла и чтения и записи. Метод open имеет следующий синтаксис:
    result = fileObjectName.open("mode");
    Это метод возвращает true, если операция прошла успешно, и false в ином случае. Если файл уже открыт, операция терпит неудачу, и оригинальный файл остаётся открытым.
    Параметр mode это строка, специфицирующая режим открытия файла. В таблице описаны эти режимы.

    Режим
    Описание

    r

    Открывает файл, если он существует, как текстовый файл для чтения и возвращает true. Если файл не существует, возвращает false.

    w

    Открывает файл как текстовый файл для записи. Создаёт новый (первоначально пустой) текстовый файл, независимо от того, существует файл или нет.

    a

    Открывает файл как текстовый файл для дополнения (записи в конец файла). Если файл ещё не существует, создаёт его.

    r+

    Открывает файл как текстовый файл для чтения и записи. Чтение и запись начинаются в начале файла. Если файл существует, возвращает true. Если не существует, возвращает false.

    w+

    Открывает файл как текстовый файл для чтения и записи. Создаёт новый (первоначально пустой) текстовый файл, независимо от того, существует файл или нет.

    a+

    Открывает файл как текстовый файл для чтения и записи. Чтение и запись начинаются в конце файла. Если файл не существует, создаёт его.

    b

    Если присоединён к одному из вышеуказанных режимов, открывает файл как бинарный/двоичный файл, а не как текстовый. Применяется только для операционных систем Windows.

    Когда приложение заканчивает использование файла, оно может закрыть его, вызвав метод close. Если файл не открыт, close терпит неудачу. Это метод возвращает true при успехе и false - в противном случае.

    Отладка Приложения Hangman

    Вы можете поэкспериментировать с JavaScript, чтобы получить представление о разработке приложений. Одна из важнейших задач - отладка. Выберите в Application Manager приложение Hangman и Debug/Отладить. Application Manager открывает окно с приложением в одном фрэйме и с отладочной информацией - в другом, слева, как показано на .
    Рисунок 4.3 Отладка приложения Hangman

    Отладка Приложения Hangman
    Заметьте, что URL будет теперь
    http://server.domain/appmgr/debug.html?name=hangman
    Вы можете сделать закладку на этот URL для удобства работы с Hangman. После этого не нужно будет выходить в Application Manager.
    Попытайтесь добавить в Hangman функцию, проверяющую, является ли введённый пользователем символ буквой (а не числом или знаком пунктуации). Можете использовать функцию InitAnswer из hangman.js для старта. После компиляции и рестарта приложения используйте закладку для запуска приложения в режиме отладки.

    Отладка Приложения

    Для отладки приложения сделайте следующее:
    Выбрать имя приложения в списке приложений и щёлкнуть Debug, как указано в разделе .

  • Загрузить URL отладки, как указано в разделе .

  • Можно использовать функцию debug для вывода отладочной информации, как описано в разделе .
    После запуска отладки приложения JavaScript Вы не сможете остановить или рестартовать его. В этих случаях Application Manager выдаст сообщение "Trace is active/Трассировка включена". Если это произойдёт, сделайте следующее:
    Закройте все окна отладки.

  • Закройте все окна с данным приложением.

  • В Application Manager выберите это приложение и щёлкните Run.

  • Теперь Вы можете остановить и рестартовать это приложение.

    Отладка в JavaScript

    JavaScript позволяет создавать сложные компьютерные программы. Как и во всех других языках, Вы можете ошибаться при написании скриптов. Отладчик Netscape JavaScript Debugger даёт возможность отлаживать Ваши скрипты.
    об использовании Отладчика см.
    .

    Отображение Выражений и Агрегатных Функций

    Операторы SELECT могут запрашивать значения, не являющиеся столбцами в БД, такие как агрегатные значения и выражения SQL. Для таких значений Cursor -объект не имеет именованного свойства. Вы можете получить к ним доступ только через использование свойства индекса массива Cursor -объекта для данного значения.
    В следующем примере создаётся курсор с именем empData, делается переход к первому ряду этого курсора и затем отображается значение, запрошенное агрегатной функцией MAX. Выполняется также проверка того, что результаты из БД верны, перед тем как использовать их:
    empData = connobj.cursor ("select min(salary), avg(salary),

    max(salary) from employees");
    if ( empData && (connobj.majorErrorCode() == 0) ) {
    rowexists = empData.next();
    if (rowexists) { write("Highest salary is ", empData[2]); }
    }
    Во втором примере создаётся курсор с именем empRows для подсчёта количества рядов в таблице, выполняется переход к ряду в этом курсоре, а затем отображается количество рядов параллельно с выполнением проверки на верность данных:
    empRows = connobj.cursor ("select count(*) from employees");

    if ( empRows && (connobj.majorErrorCode() == 0) ) {
    rowexists = empRows.next();
    if (rowexists) { write ("Number of rows in table: ", empRows[0]); }
    }

    Отображение Значений Записи

    Когда Вы создаёте курсор, он получает свойство colName для каждого именованного столбца виртуальной таблицы (отличное от свойств, соответствующих агрегатным функциям), как определено оператором SELECT. Вы можете получать доступ к значениям текущего ряда, используя эти свойства. В вышеприведённом примере курсор имеет свойства для столбцов id, name и city. Вы можете вывести значения для первого возвращённого ряда, используя следующие операторы:
    // Создаётся Cursor-объект.

    custs = connobj.cursor ("select id, name, city
    from customer order by id");// Прежде чем продолжить, убедитесь, что курсор действительно был возвращён
    // и не было ошибки БД.

    if ( custs && (connobj.majorErrorCode() == 0) ) { // Получаем первый ряд.

    custs.next(); // Отображаем значение.

    write ("Customer Name:" + custs.name + "
    ");
    write ("City: " + custs.city + "
    ");
    write ("Customer ID: " + custs.id);
    //Закрываем курсор.

    custs.close();

    }
    Сначала текущим рядом является первый ряд таблицы. Выполнение метода next передвигает текущий ряд на первый ряд таблицы. Например, предположим, что это первый ряд курсора:
    1 Sally Smith Suva
    Тогда предыдущий код выведет:
    Customer Name: Sally Smith
    City: Suva
    Customer ID: 1
    Вы можете обращаться к свойствам Cursor -объекта (или, в действительности, объекта JavaScript) как к элементам массива. Элемент массива с индексом [0] соответствует первому столбцу, элемент массива с индексом [1] соответствует второму столбцу, и так далее.
    Например, Вы можете использовать индекс для отображения тех же значений столбцов, что и в предыдущем примере:
    write ("Customer Name: " + custs[1] + "
    ");

    write ("City: " + custs[2] + "
    ");
    write ("Customer ID: " + custs[0]);

    Эта техника особенно применима внутри циклов. Например, Вы можете создать Cursor -объект с названием custs и вывести результат выполнения запроса в виде таблицы HTML с помощью следующего кода:

    // Создаётся Cursor-объект.

    custs = connobj.cursor ("select id, name, city

    from customer order by id");// Прежде чем продолжить, убедитесь, что курсор действительно был возвращён
    // и не было ошибки БД.

    if ( custs && (connobj.majorErrorCode() == 0) ) {
    write ("");

    // Отображаем имена столбцов как заголовки.

    write("");
    i = 0;

    while ( i < custs.columns() ) {

    write("");

    i++;
    }

    write(""); // Отображаем каждый ряд виртуальной таблицы.

    while(custs.next()) {

    write("");
    i = 0;

    while ( i < custs.columns() ) {

    write("");

    i++;
    }

    write("");
    }

    write ("
    ", custs.columnName(i), "
    ", custs[i], "
    "); // Закрываем курсор.

    custs.close();
    }

    Этот код может вывести примерно такую таблицу:

    ID

    NAMECITY
    1



    Sally Smith

    Suva



    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
    DB2CAE 2.1.2Не поддерживаетсяНе поддерживаетсяV5.2 V5.2V5.2
    InformixInformix Client 7.22Informix Client 7.22Informix Client 7.22SDK 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.1MS SQL Server 6.5 (драйвер 3.60)
    SQL Anywhere 5.5 (драйвер 5.00)
    MS Access 7.0 (драйвер 3.51.171300)
    Oracle Oracle Client 7.3.xOracle Client 7.3.xOracle Client 7.3.xOracle 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.111.1.111.1.1

    1Версия Oracle SQL*Net 1.1 больше не поддерживается.

    В следующей таблице дано резюме по поддержке ODBC в Windows NT для Netscape Enterprise Server и Netscape FastTrack Server.
    ODBC-КомпонентWindows NT 4.0 SP4
    ODBC ManagerMS 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.0MS Access Driver 3.51.171300 (odbcjt32.dll)
    Sybase SQL Anywhere 5.5Sybase 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 в процессе разработки

    Серверный JavaScript
    На втором этапе, показанном на , страница приложения запрашивается клиентским браузером. Машина выполнения использует исполняемый блок для просмотра исходной страницы и динамической генерации HTML-страницы, возвращаемой клиенту. Она выполняет все найденные на странице операторы серверного JavaScript. Выполнение этих операторов может добавить новые операторы HTML или операторы клиентского JavaScript в HTML-страницу. Машина выполнения отсылает затем окончательный вариант страницы по сети Navigator-клиенту, который выполняет клиентский JavaScript и отображает результат.

    Рисунок 1.4 Серверный JavaScript в процессе выполнения

    Серверный 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.customClients
  • project.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 Клиентская техника


    Сравнение Видов Техники Обслуживания Объекта client

    На дана информация для серверной техники.

    Рисунок 6.4 Серверная техника


    Сравнение Видов Техники Обслуживания Объекта client

    Имеются некоторые общие для видов (серверной и клиентской) техники вопросы. Для обоих типов техники, использующих куки, браузер обязан поддерживать протокол 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, показаны в следующей таблице.

    УстановкаЗначение

    Name
    flexi

    Web File Path/Путь к web-файлу
    $NSHOME\js\samples\flexi\flexi.web

    Default Page/Страница по Умолчанию
    fsa.html

    Initial Page/Начальная Страница
    start.html

    Client Object Maintenance/Обслуживание Объекта сlient
    client-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

    Вертикальная позиция курсора, когда пользователь щёлкает на карте изображений. Описано в разделе

    132
    uri
    Частичный 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. Ed

    Enter 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. (См. ). Также не используйте тэг