Migrating from Jaxer beta

From Aptana

Contents

Basics

The Jaxer Team is looking forward to your questions and observations in the Jaxer 1.0 forum, especially about any difficulties you have migrating applications to this version.

Why You Should Read This Page

Jaxer versions 1.0.0.xxxx RC A and 1.0.0.xxxx RC B are NEW VERSIONS of Jaxer and are release candidates for Jaxer 1.0. By this we mean the software is pretty much feature complete, and there should be few changes going forward that break existing code. However there are substantial changes between these 1.0 versions and prior (0.9, or beta) versions. This document is intended to help you understand the differences so you can migrate your applications.

There is also a lot of new functionality worth exploring in this release, such as Jaxer.Process (for running external processes) and Jaxer.Sandbox (for loading and accessing/scraping full 3rd-party web pages server-side), and we'll post more examples and guidance about them over the coming days and weeks.

Backwards Compatibility

This release of Jaxer is considerably more recent than the previous release (0.9.7.2472); we've taken the feedback received thus far and put much of it into this version.

Previous betas allowed you to use the Jaxer_Update.zip method of updating the core files. In this release (only) you must take the new release in its entirety rather than applying a delta.

Operating System and File Locations

Some files and folders have moved, e.g. your data is by default now within the local_jaxer folder hierarchy. Also, if you are using Jaxer in the Aptana Cloud, it is running on Solaris so there may be differences in the expected location of files and related objects between the Jaxer instances you run locally and those in the Aptana Cloud. If you are using Jaxer on Linux the layout will be relatively familiar, otherwise expect a few differences.

Updated APIs

Changes you'll need to implement in your existing Jaxer apps (see API docs in Studio for method details):

  1. Locate a file in the current folder
    • Old: Jaxer.Dir.resolvePath (i.e. the folder your app was located)
    • New: Jaxer.Dir.resolve
  2. Config file changed to provide a more holistic definition of the application
    • Old: configRoutes.js
    • New: configApps.js.
    • Impact: By default files will be created in the data folder. Each defined application will create a folder under data named after your defined appname to contain file and folder objects used by the app. Jaxer will still allow you to navigate to file system objects explicitly but as the default locations are changed you must update any filesystem path assumptions in your Jaxer code.
  3. Database
    • New: The Jaxer.DB object will now reference an application-specific database; this should be transparent and we have not yet seen a need to change any existing code to deal with this change. Sqlite database files, however, will now be found in the application folder (or the DEFAULT folder) inside the data folder. The config parameters object has been changed slightly: the IMPLEMENTATION property is now one of those parameters
  4. Session and session-like containers (session, page, sessionPage, and application)
    • Old: var value = Jaxer.session.get(key) and Jaxer.session.set(key, value), etc.
    • New: var value = Jaxer.session[key] and Jaxer.session[key] = value, etc.
  5. Invoking asynchronous proxy functions on the server from the client. For example, if myServerFunction(arg1, arg2) is defined on the server and myServerFunction.proxy = true; then:
    • Old: myServerFunctionAsync(callback, arg0, arg1)
    • New: myServerFunction.async(callback, arg0, arg1)

Details

Here's a more detailed list of the changes.

Web request/response flow control

  • With Jaxer.response.exit() and Jaxer.response.setContents(), you can now interrupt the default page processing flow, terminating it before it's gotten to the end of the page and controlling whether to return the serialized DOM (the part that's already been processed) or your own contents.
  • A convenience wrapper, Jaxer.response.redirect(), has been provided to make redirects a snap.

XMLHttpRequest information

    • Jaxer's web capabilities, specifically functions like Jaxer.Web.get() that use Jaxer.XHR.send(), now have access to all the information about the XMLHttpRequest. For example, you can now get all the response headers from the request.

Image loading

    • Images can now be loaded server-side and manipulated via the canvas object. [JXR-172]

JaxerManager/Logging

    • The underlying logging mechanism has been enhanced to centralize logging through a separate process, jaxerlogger, and allow for robust rotation as well as piping to an external log management system such as cronolog. See JXR-198 and JXR-215.
    • Enhanced error checks and logging have been added for jaxer manager.
    • The default logging level for JaxerManager has changed from ERROR to INFO.
    • JaxerManager now provides more explicit logging when destroying and creating jaxer instances.
    • A crash reporter tool is now built-in to provide better insight to system failure.
    • Each Jaxer instance is now set to restart after 1000 requests to better manage memory footprint. This can be changed in the JaxerManager.cfg file.

Page processing time:

    • Page processing time now respects the mozilla prefs value, dom.max_script_run_time to prevent script processing loops and terminate long running scripts.

Client-side proxy changes

    • Proxies are now injected into the browser-bound page differently: we only inject an array of proxy function names, and dynamically create them in the browser.
    • Rather than appending "Async" to each proxy function to access its asynchronous counterpart, you now call any proxy function myFunc asynchronously by invoking myFunc.async(callback, arg0, arg1, ...).
    • You can also get the URL needed for calling the server-side function on your own (e.g. via a 3rd-party Ajax library) via myFunc.getUrl(arg0, arg1, ...).

Apache Configuration changes

    • Added local_jaxer http conf file support, a local http conf file can be stored in the local jaxer folder and enabled by uncommentiing the final line in the Apache httpd.conf that ships with the standalone jaxer. This allows you a simple mechanism for customizing the standalone jaxer apache directives.
    • Filter is URL extension based only. '*' can be used to include files with no extension. The mime type content_type header is used to filter the actual requests that will be sent to Jaxer in conjunction with the file extension. [JXR-210]
    • Added JaxerDoNotFilterContentFromHandler directive, This allows jaxer to opt out from processing (in apache terms acting as a filter) content from the specified handler. This may be either a handler name specified in the conf file, or a dynamic string depending on the behaviour of the content handler you want to avoid. In the case of PHP for example the handler string is set to the content type derived from the corresponding AddType directive 'AddType application/x-httpd-php .php' would have a handler label of 'application/x-httpd-php'. Typically with PHP you may have to setup multiple directives depending on the configuration.

App management

    • You can now manage your applications' configuration through a new apps subsystem. This involves configuration via configApps.js (both default and override versions), complete separation of the Jaxer framework's internal configuration (config.js) from configApps.js, and access to the app in effect within a given request via Jaxer.request.app.
    • By default, you should not have to do anything: the default settings recognize the app via the URL of the request and assign the default path for reading/writing files, the default database settings, the stateful (session-type) persistence context, etc. automatically.
    • But you can also add your applications to configApps.js to specify exactly what DB settings, default file locations, and other parameters to use with each of them. Each app configuration entry in configApps.js has a special property called urlTest: when a request comes in, each of the app config entries in configApps.js is matched via its urlTest to the request's URL, until a match is found and that app config entry is used (and made accessible as Jaxer.request.app).
    • By default, Jaxer.Dir.resolve() and most static file-type IO functions (e.g. Jaxer.File.read(), Jaxer.File.write()) use as the default path the one specified in the current app's path and PATH properties. Note that the app's path property may be a function that takes the request's parsedUrl to return the default path for file access; the app's PATH property is the result of evaluating the path property, i.e. it's a string.
    • User data files are now stored in the local_jaxer/data folder inside a tree defined by the application PATH property. Files for Apps without specific settings will be stored under the local_jaxer/data/DEFAULT folder. Relative paths in Jaxer applications are now anchored on the derived data folder and not the containing folder of the JavaScript code.
    • The Jaxer.Request API and hence the Jaxer.request object has been enhanced to support the app management system. See its API for more details.
    • The previous configRoutes.js and the Route object are no longer present.

Simplified state (session-like) containers

    • The four stateful objects — Jaxer.session, Jaxer.page, Jaxer.sessionPage, and Jaxer.application — are still the way to set and get name-value pairs that persist within the corresponding context. But...
    • ...now these are simple objects, rather than special ones on which you need to invoke set() and get() methods. So you can just say Jaxer.session.userId = 12; and know that any web page accessed by this user will be able to use Jaxer.session.userId until the user closes their browser and thus ends their session.
    • Do not confuse Jaxer.application, where you can store name-value pairs across the entire context of the current application, with Jaxer.request.app, which gives the configuration settings (e.g. which DB to use, where to store files, etc.) for the current application.

Database API changes

    • The IMPLEMENTATION property of the database settings, currently "SQLite" or "MySQL", is now a peer of the other database properties such as PATH (for SQLite) or USER, PASS, NAME, etc. (for MySQL).
    • Added new iterator-type capabilities to SQL query execution: mapExecute iterates a SQL statement over an array of parameters, preparing them once, and returning the results as a corresponding array.
    • The result of a single query, or the results of mapExecute, will now be the number of rows affected when the query is INSERT, UPDATE, or DELETE, rather than an empty Jaxer.DB.ResultSet.
    • Added multiple new ways to navigate through an instance of Jaxer.DB.ResultSet.
    • The MySQL interface now supports multiple SQL statements (separated by semicolons) and MySQL stored procedures.

Support for native (operating system) process execution

    • A new Jaxer.Process namespace and constructor has been added. It offers two quick-and-easy static functions, Jaxer.Process.exec() and Jaxer.Process.execAsync(), to execute operating system processes. It also offers finer control over process execution by creating a new Jaxer.Process() object and calling methods on it.
    • You can pass the process any number of parameters, write string or binary data to the its STDIN, read string or binary data from its STDOUT and string data from its STDERR, and retrieve its exit status.

Jaxer Serializer

    • The Jaxer Serializer now supports serializing XML and E4X documents and can be extended to support any custom type. This means that, for instance, XML and E4X can now be passed in callbacks as objects, not just as strings. It also supports the original Crockford JSON for both serialization and deserialization.

Additional changes existing APIs

    • Jaxr.Dir.resolve() replaces the previous Jaxer.Dir.resolvePath(), and Jaxer.Dir.resolveUrl() is eliminated.
    • Jaxer.Web.resolve() usually resolves its argument into a web-type URL relative to the current request's URL, unless its argument explicitly begins with file:// or resource:// &mdash but now it also detects whether the argument contains the path "jaxer-include" and if so resolves it to a file:// type URL. When combined with a web server configuration that forbids web access to any URLs containing "jaxer-include", this lets you place any .js files that you want accessible only to Jaxer in a jaxer-include folder without worrying that your code is directly accessible on the internet.
    • The path attribute on the <jaxer:include> has been eliminated; you can always specify a file:// URL for the src attribute to fetch a file from disk rather than from the web server.

New APIs

    • Jaxer.Sandbox allows you to open external URLs inside a secured container and manipulate the content. This is really useful for mashups and screenscraping!
    • The static function Jaxer.Dir.create(path) as well as both a static function and an instance method named Jaxer.Dir.createHierarchy(path) which create the folder hierarchy needed to arrive at the given path.
    • Jaxer.Util.String.grep(): Searches an array of lines for a pattern and returns the lines that match.
    • Object manipulation: Enhanced with new Jaxer.Util.clone(obj, deep, maxDepth) and Jaxer.Util.extend(obj, extensions) functions
    • Util.Math.forceInteger(num, defaultNum) added