Aptana Jaxer Technical FAQ

These are frequently asked technical questions about Aptana Jaxer.

How is the DOM on the server related to the DOM on the browser?

Jaxer does not attempt to synchronize the DOMs on the browser and the server. While one could add to Jaxer, that would require very frequent network connections, lots of persistent state on the server that may or may not be useful, and a lot of instrumentation of the browser to make sure all changes were caught for transmission to the server (among other issues).

To understand the relationship of the DOMs, please refer to the documentation on the Jaxer page lifecycle and DOM.

Where should I put my Jaxer web content?

If you installed the Aptana Jaxer package, you'll find a folder called "public" in the top folder containing your Jaxer installation, and that's where the Apache included in Aptana Jaxer will expect your files and folders.

If you're using Jaxer within Studio, you can put Jaxer content in any project, and by default Jaxer will process any web pages in that project if it's running. Note that if a web page contains no Jaxer-specific code or markup, Jaxer will not alter the web page sent to the browser.

In either case, if you'd like Jaxer to pull in the contents of an HTML file when processing some page, you should put that included HTML file inside a folder called "jaxer-include" to ensure that Jaxer doesn't process that file before it includes it in the page. Click here for more information.

When I load a page served by Jaxer, my browser complains that "Jaxer is not defined".

If your page was served through Jaxer and made use of any of Jaxer's capabilities (e.g. you used <script runat="server"> anywhere in it), then Jaxer will have modified the page sent to your browser, and added JavaScript to your HTML that defines "Jaxer."

So to see if Jaxer processed your page, view the source of the page in your browser. You should see the following line near the top of the page:

If you see this page, "Jaxer" should be defined as a global JavaScript object in your page on the browser. If you don't see this line, perhaps Jaxer is not running, or for some reason did not process your page. If you are running Jaxer in Studio, make sure the Jaxer button is green, otherwise click it to turn on Jaxer.

I have custom configuration settings. How do I prevent the next Jaxer upgrade from overwriting them?

If you want to change some of your configuration settings, for example to use MySQL rather than SQLite, we strongly recommend you make those modifications in the local_jaxer folder. When you use Jaxer within Aptana Studio, or when you use the standalone Jaxer Package, a folder called local_jaxer is created for you automatically, as a peer of your jaxer folder. It already contains templates for files you can use to override Jaxer's default settings. When you upgrade Jaxer you'll get a new version of the jaxer folder, but your local_jaxer folder will be preserved, and its settings will override those in the jaxer folder.

Can the Apache included in Aptana Jaxer coexist with my current web server?

Absolutely! In fact, the Jaxer package was designed to be completely portable. It installs nothing on your machine and leaves nothing behind if you remove it (just delete the "Aptana Jaxer" folder). Apache launches independent of any existing web server or configuration file, and listens on port 8081 by default.

If you'd like to use Jaxer with your existing web server, we have instructions for Apache 2.x, and we'll be supporting other web servers soon.

How do I stop Apache?

On Windows, Apache is launched (not as a service) when you run the StartServers.bat file, as you can see in the attached DOS window screenshot. Just hit any key in the DOS window to stop it.

On Mac OS X, just click on "Stop Servers" or "Quit" to stop Apache and Jaxer.

How do I include HTML from one file in another page?

It's often useful to include a fragment of HTML stored in one file in a page stored in another file. For example, you can reuse an HTML fragment across multiple pages so if you change it in one place all your pages will remain consistent. To do this, simply use the <jaxer:include> element in your web page. But where should the fragment go?

Often, the HTML fragment will be in a file that's on your web server. You'd like to pull it into your page, and have Jaxer process your whole page with the included fragment in it, rather than process your fragment first — which would turn it into a whole page by itself — and then include it. And you probably don't want your users to access the fragment on its own, without the full page. To achieve all this, your fragment file needs to be in any folder named "jaxer-include". (Actually, any of the folders above it can be called "jaxer-include".) Then your web server will know not to send the fragment through Jaxer before serving it (to Jaxer), and it will know not to serve it to anyone other than Jaxer.

So a typical folder structure might be:

mainPage.html
secondPage.html
jaxer-include
   fragment1.html
   fragment2.html
   js
      myServerCode1.js
      myServerCode2.js

Note that you can put server-only JavaScript files in jaxer-include too to make sure they are not accessible to browsers.

To use fragment1.html in mainPage.html, simply use:

Note that your project folder structure is portable this way: if you move the whole project to a different location, the include will continue to work.

Alternatively, you can specify the complete location of your fragment file using the path attribute. In this case the file is taken directly from the filesystem, rather than the web server, so it must exist locally, e.g.:

How do I call my server functions synchronously or asynchronously?

For Jaxer 0.9.8 or later

When you designate a server-side function to be proxied, that is, callable from the browser, the function is replaced in the browser with a client function (or proxy): one with the same name as your original function is replaced by the following in the page sent to the browser:

This code will create the proxy function in the client. Now in your browser you can call getName('myname') as you would any other browser-side function, or call getName.async(callback,'myname') to make an asynchronous call that won't block your browser from doing other things while it goes to the server and returns with the data. Of course, that means that you need to tell getName.async what to do with the result once it returns, and for that you need a callback function on the browser:

For Jaxer 0.9.7 or earlier

When you designate a server-side function to be proxied, that is, callable from the browser, the function is replaced in the browser with two functions (proxies): one with the same name as your original function, and one with a suffix of "Async": is replaced by the following in the page sent to the browser:

Now in your browser you can call getName as you would any other browser-side function, or call getNameAsync to make an asynchronous call that won't block your browser from doing other things while it goes to the server and returns with the data. Of course, that means that you need to tell getNameAsync what to do with the result once it returns, and for that you need a callback function on the browser:

Does Jaxer have to re-process the page on every page request and every callback?

To serve a page, Jaxer needs to read and parse it, handle any server-side processing, and if the DOM has been changed it needs to turn it back into HTML for processing.

Currently, it does this on every normal (non-callback) page request, and given the strengths of the core Mozilla engine, it's pretty fast at it. It does however keep track of whether there was any server-side content to process, so soon Jaxer will remember that information and — if the page hasn't changed — it will tell the web server to not even route that page through Jaxer on future requests.

Ajax applications tend to have pages that live for a long time on the browser and make many callbacks. That makes it particularly important to minimize the overhead of callback processing. During a callback, Jaxer needs to not only make available the function being called, but also all the other functions this function might need to access. In fact, Jaxer makes available all the functions that were defined on that page when the page was served out, except the ones explicitly marked with a runat attribute of "server-nocache".

To make this efficient, Jaxer caches the compiled functions in memory, being careful to separate functions defined on different pages. Of course those functions are also kept in a central store, usually a database. When a callback is received, Jaxer can immediately access the already-compiled set of functions needed to process the request. Only if Jaxer is restarted, or the request is received by a different Jaxer that has never seen those functions (or the requested version of those functions), will it go to the database to get the appropriate version of those functions and rebuild its cache.

Watch out for callback data dependencies and closures

Functions defined on the server that have their proxy property set to true (e.g. by being in a script block with runat="server-proxy", or by directly setting their proxy property) are automatically made available in the page served to the browser. The original function definitions are stored on the server for use during callbacks. So are any functions on the same page that they could have called: basically any functions that were not explicitly set to runat="server-nocache".

But when you make the callback, and your called function executes on the server, you should make sure that whatever your function needs to run successfully is available: it can call the other server-side functions that were defined on the page (except for non-cached ones), and it can access databases, files, and certain session variables, but it should not rely upon closures to be available...

What are closures? Say you have the following bit of server-side code: Both saveData and readData get the name of the file from a single external variable, filename, so they're guaranteed to read and write to the same file. The filename variable creates a closure: saveData and readData save references to filename, and would have access to filename even when they are called from some context in which filename were not directly available (which is not the case here).

So what's wrong with this? During a callback, only functions are guaranteed to be made available again, not data. E.g. if the callback is handled by a different Jaxer instance in a pool of Jaxer processes, that Jaxer would recreate the functions cached for that page from the database, but would not recreate the filename variable or its value.

What's a good way to get around this limitation? One way is to use another function to return common data. This has other advantages, e.g. you could later change the function to get the data dynamically from a session variable or a database or a web service.

How can I perform XSLT transformations during a callback?

Mozilla comes with a very convenient XSLTProcessor, which of course means it's available in Jaxer. Here's an example of how to use it to transform an XML file in a callback and return the resulting HTML. The content is partially borrowed from the Mozilla XSLT example.

Note: To instantiate an XSLTProcessor during a callback, you must explicitly reference it off the window object! This is only necessary within functions used during callbacks, when they need to reference "global" objects.

Create a page as follows:

Now create the following files, in the same folder:

Here's the XML to be transformed, in a file called "original.xml":

And here's the XSLT transformation, in a file called "transform.xslt":

Now serve the page through Jaxer, and click the transform button. You should see:

How do I suppress the display of revealing Jaxer errors in the browser?

The Jaxer beta is shipped with the server side exception and error handling configured for a development environment.

What this means is that messages generated server-side will be propagated to the browser for simpler debugging and faster development. If the error occurred before the final processing of the page, the HTML returned to the browser may well contain server-only code. To prevent such code and detailed error messages to ever be seen by users in a production environment, we highly recommend you change the Config.DISPLAY_ERRORS option before going live with your application.

The following code will generate an error, that with the default configuration is displayed in the browser as shown below:

If you set the Config option Config.DISPLAY_ERRORS in local_jaxer/config.js to be false, server-side errors cause the output page to be completely replaced by one containing the following message:

The error data is still logged to the Jaxer log file so no failure information is lost.

Using javascript libraries during callbacks

Ok, here's a simple code sample that demonstrates how to load jQuery and use it in a server callback.

The key to understanding what is happening with this, is to understand when the jaxer server instantiates a DOM.

Let's review, the flow from disk to browser is roughly this.

  1. Get the page from disk
  2. Spin up the server process and load the page. at this point you have a DOM(1) on the server that has not been passed to the client.
  3. Complete the page processing (cache functions, run js etc) and serialize the DOM(1) to the client.
  4. Client gets the page and renders its own DOM(2).
  5. Client requests callback function
  6. Jaxer creates environment for callback to execute within (including a DOM(3))
  7. Callback runs and returns.

NOTE.

DOM(1) exists on the server during the page processing and is then discarded.
DOM(2) exists on the client and can be dynamically changed
DOM(3) exists on the server for the duration of the callback. it has no knowledge of the DOM inside the client browser or the DOM created during initial page processing.

It is important to understand these DOMs are not connected, in any way that would allow changes to be synchronized between them.

So this means that when we do a callback, we have to ensure that the environment is setup the way that we want it. To do this we have the special 'oncallback()' function that can be defined on a page.

To get the jQuery library to be avaailable during a callback we specify the 'autoload=true' attribute on the src tag, this means that when a callback is made to the page the jaxer instance will load that library into it's DOM before any callback processing takes place.

So when you run this code you should see something like the following in the log

19:06:31 06/05/2008 [  4676] [INFO] [JS Framework] [framework.] http://127.0.0.1:8000/index.html
19:06:31 06/05/2008 [  4676] [INFO] [JS Framework] [framework.] Setting up environment for the callback
19:06:31 06/05/2008 [  4676] [INFO] [JS Framework] [framework.] jQuery already loaded.
19:06:31 06/05/2008 [  4676] [INFO] [JS Framework] [framework.] first: OK I'm in the callback...
19:06:31 06/05/2008 [  4676] [INFO] [JS Framework] [framework.] first: ...callback completed
19:06:31 06/05/2008 [  4676] [INFO] [JS Framework] [framework.] Setting up environment for the callback
19:06:31 06/05/2008 [  4676] [INFO] [JS Framework] [framework.] jQuery already loaded.
19:06:31 06/05/2008 [  4676] [INFO] [JS Framework] [framework.] second: OK I'm in the callback...
19:06:31 06/05/2008 [  4676] [INFO] [JS Framework] [framework.] second: ...callback completed

How do I configure Jaxer to use my proxy settings?

Much like any browser can be configured to route its network traffic through a proxy, so too Jaxer (starting with 0.9.1) can be set to work with a proxy. In fact, to do so, you just use the same preferences used by Firefox. To see a list of such preferences, launch Firefox and "browse" to about:config and look for network.proxy.* where you'll find network.proxy.type, network.proxy.http, network.proxy.http_port, and so on.

To set these, edit your local_jaxer/config.js and add the following lines: Of course, you may need to use different values or even different preferences. When you restart Jaxer, it should route traffic (e.g. when using Jaxer.Web.get(...)) through your proxy server.

Note that it's important to use the proper type for each preference, e.g. an integer for http_port and a string for the others. For networking-related preferences, refer to http://developer.mozilla.org/en/docs/Mozilla_Networking_Preferences for a list of options.

How do I use the Jaxer logging system to log messages?

The Jaxer framework includes a logging system, and is itself liberally instrumented with logging statements. The Jaxer logging framework is similar to log4j and other multi-level, multi-module logging systems. Briefly, you can instrument your code with logging statements at various levels, and if the current logging level is at or below a statement's level the statement will write to the log.

The six levels are, in increasing weight: trace, debug, info, warn, error, and fatal. By default, all modules (including the generic module) are set to log all messages at or above info.

To use the generic logging module (i.e. log messages that aren't specific to any module), use the static methods off Jaxer.Log:

Normally you will only see the last 4 of these produce anything in the log, since the first two are below the default level of info. You can change that, e.g. in the Jaxer shell, or in your local_jaxer/configLog.js where you can see one or more or even all the modules to log at a lower level. Try Jaxer.Log.forModule("DB").setLevel(Jaxer.Log.TRACE); or Jaxer.Log.setAllModuleLevels(Jaxer.Log.INFO); and note that the levels themselves are indicated by the all-caps constants.

It's better to create your own module-specific loggers, because then you can selectively turn on logging for different parts of your code. It's very easy: e.g. You can use any name you want for your modules. Whenever you use a name that has not been used before, a new module logger is created for you, and you get back a handle to it, as shown above. If you use one that's already been used, you just get back a handle to that one.

Note also that by default any log messages at or above the Jaxer.Log.ERROR level will automatically also contain a stack trace. As usual, you can control that through configLog.js.

Where can I find the configuration information for a standalone Jaxer with apache?

Here are some of the basic things about the folder structure of the “Jaxer Package with self-contained Apache on Windows”. (The top most folder is Aptana Jaxer, eg “C:\JAM\Aptana Jaxer” if you unzip it under C:\JAM).

Apache configuration: the main apache configurations related with Jaxer are in jaxer/confs/jaxer-win.httpd.conf. This file is referenced from Apache22\conf\httpd.conf. It specifies information such as Jaxer server and port, file types that will be processed by Jaxer.

Mod_jaxer: the filter/handler that communicates between Apache and Jaxer is under jaxer/connectors. Two of them are included; one works with Apache 2.2 (mod_jaxer.so), and the other works with Apache 2.0 (mod_jaxer20.so). It is referenced in the Apache configuration file.

Jaxer executables: they are under the jaxer folder. JaxerManager is the one you would start, and it starts and manages Jaxer’s.

Jaxer preferences: the preferences are under jaxer/defaults/pref. These settings mainly (although not all of them) control the amount of logging. If you modify the preferences, you should restart JaxerManager.

Logs: all logs are under logs. If you turn on the debug logging or protocol dumping, the jaxer log can grow quickly.

Default Webroot: the default is public. You can put your test page there and load it with http://localhost:8081/ to test it.

Can I Use Jaxer with ODBC Drivers?

Yes, you can use Jaxer to access datasources accessible though ODBC

The sample code below demonstrates how to use the mozilla native database support to access an ODBC driver. The code is setup to access a preconfigured DSN ('SQLEXPRESS') and run a query against a table named 'jaxer'. Example results are shown after the code

Included in the comments of the code are links to external documents containing documentation or further examples for the Mozilla native database support.

This sample code is only supported with Jaxer build 2109 or later. you can download the latest version here

When this code is run the output is logged to the Jaxer log file. It should look something like this.

00:01:48 02/13/2008 [  2204] [INFO] [JS Framework] [odbc.] ------------------------------------------------------
00:01:48 02/13/2008 [  2204] [INFO] [JS Framework] [odbc.] comment                                 | tags                                   
00:01:48 02/13/2008 [  2204] [INFO] [JS Framework] [odbc.] ------------------------------------------------------
00:01:48 02/13/2008 [  2204] [INFO] [JS Framework] [odbc.] Jaxer Baby!                             | groovey                                
00:01:48 02/13/2008 [  2204] [INFO] [JS Framework] [odbc.] No Sleep til Jaxer                      | beastie                                
00:01:48 02/13/2008 [  2204] [INFO] [JS Framework] [odbc.] It's Jaxtastic!                         | plastic                                
00:01:48 02/13/2008 [  2204] [INFO] [JS Framework] [odbc.] ------------------------------------------------------

Jaxer debug/trace settings for basic trouble shooting

Jaxer has configuration settings that allow logging levels be adjusted. Here are some of the settings that you can turn on/off when trouble shooting a problem (Assuming windows platform here).

mod_jaxer (applicable only if apache is configured talking to Jaxer):
This is the module that apache uses talking to Jaxer. The loggings generated by this module are in your apache log (“Aptana Jaxer\logs\apache_error.log” if using the shipped apache server).
To generate extensive loggings, go to your httpd.conf (“Aptana Jaxer\Apache22\conf\httpd.conf” if using the shipped apache server.), change the LogLevel to debug, and restart apache.
LogLevel debug

JaxerManager:
JaxerManager manages the individual Jaxers. It is the bridge between the webserver connector (eg mod_jaxer) and jaxer. JaxerManager writes logs in the same file as Jaxer does. The log file is jaxer.log under “Aptana Jaxer\logs” if you are using the standalone Jaxer install.
You can turn on trace either from the JaxerManager command line (--trace=on) when you start JaxerManager or issue a (set trace on) command through its command port. You can use the utility program tellJaxerManager to do it.
From command line:
JaxerManager –trace=on
After JaxerManager has started:
tellJaxerManager “set trace on”
To turn off the trace,
From command line:
JaxerManager –trace=off
After JaxerManager has started:
tellJaxerManager “set trace off”

Jaxer:
Jaxer is the main process that does the work. It has a few settings that control various logging levels. All Jaxer logs go to the same log file as JaxerManager.

Turn on protocol dumping:
When it is turned on, Jaxer logs all network traffic between it and the webserver connector. The setting is in defaults\pref\Jaxer_prefs.js under the jaxer folder (Aptana Jaxer\jaxer\defaults\pref\Jaxer_prefs.js if using the shipped apache server.).
pref("Jaxer.dev.DumpProtocol", true);
The change requires restarting jaxer. To turn it off,
pref("Jaxer.dev.DumpProtocol", false);

Other Jaxer settings:
In the same Jaxer_prefs.js file, the following settings can be turned on (true) or off (false). Note that these settings control individual levels. Thus to get the maximum loggings, you should setting all of them to true.
pref("Jaxer.CoreTrace.EnableWarning", true);
pref("Jaxer.CoreTrace.EnableInfo", true);
pref("Jaxer.CoreTrace.EnableDebug", true);
pref("Jaxer.CoreTrace.EnableTrace", true);

The configLog.js (under “Aptana Jaxer\local_jaxer\conf” if you are using the standalone Jaxer install) contains additional settings mainly controlling the loggings for server-side javascript execution. You can edit the function() body to adjust the logging levels. Your settings here override the settings in jaxer\framework\configLog.js.

Using configRoutes.js

ConfigRoutes.js was removed from Jaxer with 0.9.8, it's functionality has been encapsulated within configApps.js

Jaxer provides a mechanism to identify an application by it's URL structure, this is controlled by the 'configRoutes.js' configuration script.

The Jaxer global routing object (Jaxer.Config.routes) holds an array of javascript functions that return either a NULL, if the url doesn't match the rule, or, a 2 value array, if the url matches the rule, the first value is the identifier for the application and the second value is the identifier for the page. These identifiers are used to manage script access to the Jaxer application and page containers.

The example above would create two applications predicated on the folder structure, the first,the ToyStore application, would be active for any pages server from the myApps/toys folder, the second from the myApps/books folder. These would have an application identifer (Jaxer.application.key) of 'ToyStore' and 'Bookstore' respectively, with each page being identified by it's full URL.

In the event that a URL doesn't match any of the provided rules, the default Jaxer rules would apply which provides an application name based on the fullpath to the folder, and a page context based on the full path to the document being served.

How do I fix Components.classes[MYSQL50_CLASS_ID] is undefined - Ubuntu Only.

For ubuntu users expereiencing this erro, download the following file and unzip and place in the jaxer/components folder of your jaxer install.

libjxMySQL50.zip

AttachmentSize
libjxMySQL50.zip599.03 KB