Applications
This section shows how to use MSP tags in a number of specific applications.
XML
XML is a general data format that is becoming increasingly important. Data that is formatted in XML can readily be used by applications that are able to process it. In this case, the choice of an XML format means that you will save considerable development effort. In addition, there is an increasing number of existing data formats that use XML. Some of the more important for mathematical and scientific purposes include XHTML (an XML-compliant version of HTML), MathML (a way to store mathematical information) and SVG (a graphics format). A large list of XML applications is available here.
Wolfram Language contains a large number of features for working with XML, all of which are available in MSP tags. XML can be very useful for MSP with its support for specific XML applications and as a general format for data interchange. The use of MathML, SVG and XHTML will be covered in their own sections. This section will give an overview of XML and the XML features of Wolfram Language. It will also give some examples of why this functionality is useful to the Wolfram Web Engine.
Introduction to XML
This section will give a very brief introduction to XML. For more information, go to one of the many references, such as those detailed here, for example "XML in 10 Points".
A sample XML document is shown here:
<?xml version="1.0"?>
<library>
<book>
<title>A New Kind of Science</title>
<author>Stephen Wolfram</author>
</book>
<book>
<title>The Lord of the Rings</title>
<author>J.R.R. Tolkien</author>
</book>
</library>
This example shows a data format for a library. The library contains books, and each book has a title and an author. This shows how XML is suitable for structured data. In addition, you can see how XML looks a little like HTML, except that the tags (words bracketed by "<" and ">") are not restricted to a fixed set since new tags that are suitable for a particular application can be introduced. Unlike HTML, the format of XML is stricter, with a valid XML document being required to follow rules that do not apply to HTML. This is demonstrated in the next section.
XML Compliance
One issue with XML is that documents must be well formed, following the rules of XML. Some basic examples of compliance are described in this section.
An XML document must include a header. For example, it must start with something like the following:
<?xml version="1.0"?>
Empty elements must either have an end tag, or the start tag must end with "/>". Thus, the following is legal:
<br/><hr/>
<br><hr>
For non-empty tags, the end tag is required. Thus, the following is legal:
<p>Here is a paragraph.</p><p>Here is another.</p>
<p>Here is a paragraph.<p>Here is another.
Wolfram Language Support for XML
Wolfram Language provides some very convenient ways to work with XML. Many of these are based on the strong correspondence between structured XML documents and Wolfram Language expressions (the basic data type of Wolfram Language). This makes it easy to import XML data into Wolfram Language and then work with it. This section gives a very brief introduction to working with XML in Wolfram Language; more information is available in the online documentation.
The following is a simple example:
This XML can be imported into Wolfram Language, which represents it with symbolic XML. Because of the nature of Wolfram Language expressions, symbolic XML is a Wolfram Language–native form of XML that is isomorphic to textual XML:
You can use standard Wolfram Language programming features to process symbolic XML, for example to extract all the authors:
This outputs the new XML expression:
This type of transformation can, of course, be done in other ways. For example, the use of XSLT stylesheet technology provides one way. However, there is an overhead to setting up an XSLT stylesheet to make the transformation. The use of Wolfram Language, with its uniform programming principles, is often a quick and simple way to carry out the task.
There are many more features of Wolfram Language XML tools, for example working with attributes, entities, namespaces, validation and CDATA. More information is available from the Wolfram Language documentation.
MSP XML Applications
Many MSP applications involve generating HTML to be read by browsers. However, the output from an MSP site may not go to a browser; it may involve some data to be read by an application that will then do further processing. This section will study an example that shows how this can be done.
The source for this example is in WolframWebEngine/Examples/XML/Phone.jsp and WolframWebEngine/Examples/XML/Processed.jsp. It also uses an XML file WolframWebEngine/Examples/XML/phone.xml. If you installed the Wolfram Web Engine as described previously, you should be able to connect to this JSP via http://localhost:8080/webengine/Examples/XML/Phone.jsp. (You may have some other URL for accessing your server.)
<?xml version="1.0"?>
<EmployeeList>
<Person Name="Tom Jones" Email="tomj" Phone="235-1231" />
<Person Name="Janet Rogers" Email="jrogers" Phone="235-1129" />
<Person Name="Bob Norris" Email="bobn" Phone="235-1237" />
<Person Name="Kit Smithers" Email="ksmit" Phone="235-0729" />
<Person Name="Jamie Lemay" Email="jlemay" Phone="235-6393" />
</EmployeeList>
The contents of Processed.jsp are shown here:
<%@ page contentType="text/xml"%>
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>
<msp:evaluate>
xml = Import[ToFileName[MSPPageDirectory[], "phone.xml"], "XML"] ;
xml = First[Cases[xml, _XMLElement]];
If[MSPValueQ[$$patt],
xml = DeleteCases[xml,
XMLElement["Person", {___,
"Name"->n_/;!StringMatchQ[n, $$patt], ___}, _], Infinity]
];
ExportString[xml, "XML"]
</msp:evaluate>
This example first imports the XML file into Wolfram Language. It uses the command MSPPageDirectory because the XML data is located in the same directory as Processed.jsp. It then checks to see if a parameter patt was sent. If this is the case, then it uses this to discard XML elements that do not match this name. You should be able to see the operation of this parameter with a URL such as http://localhost:8080/webengine/Examples/XML/Processed.jsp?name=T. (You may have some other URL for accessing your server.) It ends by converting the symbolic XML into a string version of the XML and returning this.
Of course, you may want to use this XML data for further processing. If you have a system that is XML aware, this is quite straightforward. One useful application that is XML aware is, of course, the Wolfram Engine. For example, the following will call your MSP site and retrieve the information:
You may even wish to use this in a Wolfram Language program:
Of course, your client could be written in some system other than Wolfram Language, such as Visual Basic, Python or Java.
Using XML as an interchange format for communication between two programs is discussed in more detail in the section on web services.
MathML
MathML is designed to allow mathematical, scientific and other technical information to be served, received and processed on the World Wide Web. It is an official recommendation of the World Wide Web Consortium (W3C) working group on mathematics. Users of MSP tags can benefit from MathML in a number of ways. They can use MathML for documents that contain a mixture of mathematics and text, they can generate MathML dynamically on their MSP site and they can use a MathML entry mechanism to enter mathematical notation into their web browser and send this to the Wolfram Web Engine for computation.
Wolfram Research has long been involved in the development of MathML, both as a founding member of the mathematics working group of the W3C and as the host of the first two official MathML conferences in 2000 and 2002. Wolfram Language contains many features for working with MathML and there is a strong relationship between the Wolfram Language typesetting system and MathML.
One resource for learning more about MathML is the Wolfram Research–sponsored website MathML Central. A section describing the evolution of MathML and some of the issues involved in developing a mathematical language suitable for a computation system such as Wolfram Language is found on the site's history page.
If you are not interested in the specific details of how MathML works and just want to use MathML in your output, then you should go to the sections on generating MathML and sending MathML.
Embedding MathML in Web Documents
This section discusses how documents can be written that mix both mathematics and text. These documents are written in XML format and use both MathML and XHTML (the XML-compliant form of HTML). The Wolfram Web Engine contains functions that do all of this automatically, so you do not need to read this unless you wish to learn more about the details of how browsers support MathML.
XHTML
XHTML is an XML-compliant form of HTML, available as an official W3C recommendation. It is very similar to HTML, except that for a document to be valid, it must follow the rules of XML. (Some of these were described in the previous section.) To use documents that mix mathematics and text, XHTML is required. Use of XHTML is needed anyway, since the W3C intends that HTML will not be developed further.
The following sample XHTML document is very similar to HTML, except for the initial XML declaration and the DTD reference. The latter can be used by an XML parser to validate that the input document is indeed valid XHTML. This demonstrates one of the benefits of XML technology. That is, a parser can validate a document, checking details—such as the different tags being in the correct places and holding the correct number of arguments—without specializing in the particular flavor of XML. The reference to the DTD is not required; however, it is necessary if the document is to be validated:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Basic XHTML Document</title>
</head>
<body>
<h1>XHTML</h1>
<p>This is a basic XHTML document.</p>
</body>
</html>
This document can be read by modern web browsers and will display in the expected fashion.
XHTML and MathML
To add mathematics and other technical notation to a text document, it is possible to write one document that contains both XHTML and MathML. A sample document follows:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"
"http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd" [
<!ENTITY mathml "http://www.w3.org/1998/Math/MathML">
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Basic XHTML+MathML Document</title>
</head>
<body>
<h1>XHTML+MathML</h1>
<p>Here is a math expression.</p>
<math xmlns='http://www.w3.org/1998/Math/MathML'>
<msup>
<mi>x</mi>
<mn>2</mn>
</msup></math>
</body>
</html>
This can be read into a browser that provides native support for MathML and will be read as expected. Note the reference to a DTD that allows the embedding of MathML into XHTML to form an XHTML + MathML document.
Rendering XHTML and MathML Documents
The previous section showed how to embed MathML into XHTML, creating documents that mix text and mathematics. It also explained that this does not work with browsers that rely on a plugin mechanism. This section shows how to write documents that will work in a wide range of browsers.
To support MathML in browsers using a plugin mechanism, the document must use special tags that are relevant to the particular plugin used. If the browser supports MathML natively, then no special tags are needed. Of course, an author does not want to produce different versions of each document specific to each rendering technology. The solution is to make use of XSLT stylesheet technology to convert the document in the browser before it is viewed. This automatically inserts any special tags that are needed for plugins. An XSLT stylesheet that implements this solution is available from the W3C math site.
Here is a document that uses the MathML stylesheet:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="http://www.w3.org/Math/XSL/mathml.xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Basic XHTML+MathML Document</title>
</head>
<body>
<h1>XHTML+MathML</h1>
<p>Here is a math expression.</p>
<math xmlns='http://www.w3.org/1998/Math/MathML'>
<msup>
<mi>x</mi>
<mn>2</mn>
</msup>
</math>
</body>
</html>
By using an absolute reference to the stylesheet, documents that use the stylesheet found on the W3C site can be moved from one server to another or saved locally and continue to work.
Note that the XHTML + MathML document shown that uses the MathML stylesheet does not contain a DOCTYPE declaration. This is, of course, a limitation because the document cannot now be validated. Another consequence is that the XML system that renders it will not be aware of any special entity names.
Here is an example that uses a named entity reference, ⁡:
<math xmlns='http://www.w3.org/1998/Math/MathML'>
<mrow>
<mi>sin</mi>
<mo>⁡</mo>
<mrow>
<mo>(</mo>
<mi>x</mi>
<mo>)</mo>
</mrow>
</mrow>
</math>
This example uses the numerical value ⁡. It is the preferred form:
<math xmlns='http://www.w3.org/1998/Math/MathML'>
<mrow>
<mi>sin</mi>
<mo>⁡</mo>
<mrow>
<mo>(</mo>
<mi>x</mi>
<mo>)</mo>
</mrow>
</mrow>
</math>
If you want to find the numerical value for any character, you can use the Wolfram Language function ToCharacterCode to generate the numerical value and BaseForm to generate the hexadecimal form. For example, the Unicode value of a capital phi can be found as follows:
Further information on the appropriate numerical values can be found at the MathML site, as well as at the Unicode site.
Generating MathML from MSP
Certain MSP applications generate results that contain mathematical expressions suitable for formatting with MathML. This section shows how to generate MathML with MSP and take advantage of the rendering techniques described in the previous section.
The main Wolfram Web Engine documentation describes how MathML can be generated with MSPFormat using a format style of MathMLForm. The following will format the expression expr into MathML:
<msp:evaluate>
MSPFormat[ expr, MathMLForm]
</msp:evaluate>
MathML comes in two different varieties: presentation MathML specifies the appearance of the MathML, whereas content MathML attempts to specify what the MathML means. Since MathML contains no general extension mechanism, the amount of information that can be encoded with content MathML is limited. However, if presentation MathML is generated from Wolfram Language, it will always work when sent back to Wolfram Language.
It is also possible to use other formatting styles, such as StandardForm or TraditionalForm, in which case the format type RawMathML should be selected, as shown here.
The following shows how to generate presentation MathML:
<msp:evaluate>
MSPFormat[ expr, TraditionalForm, PresentationMathML]
</msp:evaluate>
The following generates content MathML:
<msp:evaluate>
MSPFormat[ expr, TraditionalForm, ContentMathML]
</msp:evaluate>
Tools for working with MathML typically support both content and presentation.
MathML Integrate Example
This example JSP uses the MathML stylesheet. The page is actually a combination of two JSPs, IntegrateForm.jsp and IntegrateXSLT.jsp, that use JavaScript. They are closely modeled on the standard MSP examples PlotScript.jsp and PlotScript1.jsp. The source for these MathML examples is available in WolframWebEngine/Examples/MathML. If you installed the Wolfram Web Engine as described previously, you should be able to connect to this JSP via http://localhost:8080/webengine/Examples/MathML/IntegrateForm.jsp. (You may have some other URL for accessing your server.)
You first see the source for the input page, IntegrateForm.jsp:
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>
<html>
<head>
<title>MathML Example: Integrate a Function</title>
<script>
function integrate(f, page)
{
if ( page == 1)
pageToLoad = "IntegrateXSLT.jsp"
else if ( page == 2)
pageToLoad = "IntegrateXML.jsp"
else
pageToLoad = "IntegrateMathPlayer.jsp"
win = window.open( pageToLoad + "?fun=" + URLescape(f.fun.value), "integrate",
"toolbar=none,resizeable=yes,width=450,height=350");
}
</script>
</head>
<body>
<h1>MathML Example: Integrate a Function</h1>
<form action="IntegrateForm.jsp" method="post">
Enter a function to be integrated: <br/>
<input type="text" name="fun" size="24" value="<msp:evaluate>MSPValue[$$fun, "Sin[x]^2"]</msp:evaluate>"/>
The following uses the MathML XSLT style sheet.
<input type="image" name="btnSubmit" src="../../Resources/Images/Buttons/xslt.gif" onclick="integrate(this.form, 1)"/> <br/>
<i>Uses the general MathML XSLT style sheet, this is the most general solution.</i>
The following are alternatives for rendering MathML. They are not
general solutions, but are included for demonstration purposes.
<input type="image" name="btnSubmit" src="../../Resources/Images/Buttons/xml.gif" onclick="integrate(this.form, 2)"/> <br/>
<i>Returns XHTML+MathML, suitable for a browser with native MathML support.</i>
<input type="image" name="btnSubmit" src="../../Resources/Images/Buttons/mathplayer.gif" onclick="integrate(this.form, 3)"/> <br/>
<i>Uses MathPlayer specific markup, suitable if you have MathPlayer installed.</i>
</form>
This example shows how MathML can be generated from MSP.
</body>
</html>
This is standard HTML. When the input button is clicked, a JavaScript function is called that extracts the input from the input field and calls the JSP IntegrateXSLT.jsp, which then opens in a new window. The contents of IntegrateXSLT.jsp are shown here:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/webengine/Resources/XSL/mathml.xsl"?>
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Integrate Result</title>
</head>
<body>
<msp:evaluate>
MSPPageOptions[ "ContentType" -> "text/xml"];
fun = Unspecified;
int = Unspecified;
If[ MSPValueQ[ $$fun],
fun = MSPToExpression[ $$fun];
int = Integrate[ fun, x];
If[ Head[int ] === Integrate, int = Unknown]] ;
</msp:evaluate>
Integration of a function, formatting into MathML.
<table border="2" rules="all">
<thead>
<tr>
<th>Function</th><th>Integral</th>
</tr>
</thead>
<tr>
<td align="center"><msp:evaluate> MSPFormat[ fun, MathMLForm]</msp:evaluate></td>
<td align="center"><msp:evaluate> MSPFormat[ int, MathMLForm]</msp:evaluate></td>
</tr>
</table>
</body>
</html>
This uses the MathML stylesheet, which here is assumed to be installed in the Wolfram Web Engine web application in the directory XSL. The output content type is set to text/xml, and the necessary computation in Wolfram Language is carried out.
When this example works, it might be interesting to use the View Source menu of your browser. It should be noted how the MathML flows naturally with the XHTML. Also note how the document does not state the physical size of each mathematical expression. This is very useful because the size will only be known accurately when the document is rendered in the browser.
The actual example code delivered with MSP is a little more complicated since it contains alternatives for rendering directly with MathPlayer and for generating XHTML + MathML. However, the one shown previously that uses the MathML stylesheet is the most general solution. The others are included in the example for demonstration purposes.
SVG
SVG is a language for describing two-dimensional graphics in XML. Like MathML, it is an official recommendation of the W3C. It provides a number of benefits for users of MSP. First, since it is a vector-based format, the results often have a higher quality than is typically the case with image formats. This is very much the case when considering print output. Second, for many types of image, the actual file size is often quite small, especially compared with image formats. Third, it supports a number of dynamic and interactive features. Wolfram Language can generate SVG from graphics, and this section will give some examples of web usage involving SVG.
A utility package is provided with the Wolfram Web Engine that supports adding the necessary tags. This section will give some simple examples of the use of this package with the Wolfram Web Engine.
Plotting with SVG
The source for this example is in WolframWebEngine/Examples/SVG/Plot.jsp. It is closely related to the basic example Plot.jsp. If you installed the Wolfram Web Engine as described previously, you should be able to connect to this JSP via http://localhost:8080/webengine/Examples/SVG/Plot.jsp. (You may have some other URL for accessing your server.)
An extract of the source follows:
<form action="Plot.jsp" method="post">
Enter a function:
<input type="text" name="fun" size="24" value="<msp:evaluate>MSPValue[ $$fun, "Sin[x]^2"]</msp:evaluate>"/> <br/>
Enter a number:
<input type="text" name="x1" size="24" value="<msp:evaluate>MSPValue[ $$x1, "10"]</msp:evaluate>"/> <br/>
<input type="image" name="button" src="../../Resources/Images/Buttons/evaluate.gif"/>
</form>
</div>
<div class="section">
<msp:evaluate>
Needs["MSP`SVG`"]
</msp:evaluate>
<msp:evaluate>
MSPBlock[{$$fun, $$x1},
SVGShow[Plot[$$fun, {x, 0, $$x1}]]
]
</msp:evaluate>
This is very similar to the basic example Plot.jsp. The differences between the two are the loading of the SVG support package and the use of the SVG plotting function SVGShow.
SVG Animations
SVG supports a number of animation and interaction features. This example will demonstrate the use of SVG animations.
The source for this example is in WolframWebEngine/Examples/SVG/NDSolvePlot.jsp. If you installed the Wolfram Web Engine as described previously, you should be able to connect to this JSP via http://localhost:8080/webengine/Examples/SVG/NDSolvePlot.jsp. (You may have some other URL for accessing your server.)
The source contains an HTML form that sets up a number of input fields to collect the equation, starting and ending points, and initial conditions. These are then fed to a function that solves the differential equation and returns a plot of the result formatted as SVG. The SVG is then displayed with the function SVGDisplay, which is defined in the package MSP`SVG`. The code, which inserts the plot, is shown here:
<msp:evaluate>
MSPBlock[ {$$eqn, $$t0, $$init1, $$init2, $$t1},
svg = NDSolveToSVG[ $$eqn, {$$init1, $$init2}, {$$t0,$$t1}] ;
SVGDisplay[ svg, {400, 300}]]
</msp:evaluate>
The actual definition of the function that creates the SVG is shown here. This solves the differential equation and generates a plot of the result. It then generates symbolic XML, which represents the SVG of the result, using the function XML`SVG`GraphicsToSymbolicSVG. Next, it finds the points that represent the plot of the result and uses these to form an SVG animation of a red ball, which moves along these points. This animation is inserted into the SVG to form a new result, which is returned to be plotted:
NDSolveToSVG[ eqn_, init_, lims_List]:=
Module[ {sol, dep, t, int, t0, t1},
{o,dep,t} = EquationToVariables[ eqn] ;
{t0, t1} = lims ;
sol=NDSolve[Append[init,eqn],dep,{t,t0,t1}];
{int0, int1} = Part[dep /. First[ sol],1,1];
If[ t0 < int0, t0 = int0];
If[ t1 > int1, t1 = int1];
p=ParametricPlot[ {dep[t],dep'[t]} /. sol,{t,t0,t1}, ImageSize -> 400];
xml = XML`SVG`GraphicsToSymbolicSVG[p];
pts="M"<>
First[Cases[ xml,
XMLElement["polyline",{"fill" -> _,"points" -> x_},_]->x, Infinity]];
newElem=XMLElement["circle",
{"cx"->"0","cy"->"0","r"->".1","fill"->"red", "stroke"->"blue",
"stroke-width"->"0.01"},
{XMLElement[
"animateMotion",{"dur"->"6s","repeatCount"->"indefinite",
"rotate"->"auto", "path" -> pts},{}]}];
newXML=xml/.x:XMLElement["polyline",___] -> Sequence[x,newElem] ;
ExportString[newXML,"XML"]
]
There are a number of other ways of obtaining interactive results with SVG. For example, JavaScript can interact with and manipulate the SVG tree, thereby supporting interactive features such as popups when the mouse is moved over a graphic.
HTML Formatting
One of the advantages of the HTML templating technique that MSP provides is that there is often little need to try and generate HTML formats with Wolfram Language programs. In fact, many of the HTML formatting issues can be left to web designers who can use their standard tools. However, sometimes it is useful to apply some HTML formatting functions to Wolfram Language expressions. This is particularly the case for HTML tables. In order to allow this, an HTML utility package is provided with the Wolfram Web Engine that supports table-formatting functions. This section will explore the use of this HTML formatting. A more general discussion of output is available in the section on evaluation formatting.
Remember that if you want to return HTML that is not generated by the HTML package, you should construct your own string of HTML and return this, as shown in the following example:
The HTML Functions
The HTML functions are contained in a package, MSP`HTML`, which is part of the Wolfram Web Engine layout. Since the package is loaded when the Wolfram Web Engine starts, there is no need to load the package manually. However, if you wish to use it in Wolfram Language outside of the Wolfram Web Engine, you will need to copy the package into your AddOns/Applications directory, described in a previous section.
HTMLTableForm
As explained previously, the MSP`HTML` package is available for the Wolfram Web Engine and can be installed into regular Wolfram Language. It can then be loaded, as shown here:
The function HTMLTableForm takes an input and formats it into an HTML table:
It takes a TableHeadings option that works similar to that of TableForm:
If you wish to apply special formatting to each element, you can provide a formatting function as a second element. The formatting function must return a string. Here, every element is formatted into MathML:
The default formatting function for HTMLTableForm is HTMLFormat, which is described in the next section
Any string arguments to HTMLTableForm are assumed to be already formatted and no more formatting is applied. This allows it to take the output of other MSP functions such as MSPShow or MSPFormat.
HTMLFormat
As explained previously, the MSP`HTML` package is available for the Wolfram Web Engine and can be installed into regular Wolfram Language. It can then be loaded, as shown here:
The function HTMLFormat provides some useful functionality for formatting expressions into HTML. It is suitable for formatting small expressions, such as numbers:
It is less suitable for formatting large expressions, since everything will come out in InputForm:
For larger expressions, the recommendation is to use one of the versions of the formatting function MSPFormat to gain a result in an image format or MathML.
HTMLSelect
As explained previously, the MSP`HTML` package is available for the Wolfram Web Engine and can be installed into regular Wolfram Language. It can then be loaded, as shown here:
The function HTMLSelect provides a useful way to generate select tags with MSP. It takes a list of the different options and the name to be used when the selection is submitted:
It is also possible to set selections by using the option SelectedOptions. In this example, the option labeled "a" will be selected:
By default, the values for the option tags are chosen automatically. It is also possible to set these with an argument:
The option SelectedValues can be used to set a selection based on the values:
The selection options can take a list of values to set multiple selections:
If no values are given, the SelectedValues option can use the numerical values:
HTMLCheckbox
As explained previously, the MSP`HTML` package is available for the Wolfram Web Engine and can be installed into regular Wolfram Language. It can then be loaded, as shown here:
The function HTMLCheckbox provides a useful way to generate an input checkbox tag with MSP. It takes the name to use when the checkbox is submitted as an argument:
If a second argument is given, this is used to determine whether or not the box is checked. In the following example, the checkbox is checked:
MSP Examples
A number of MSP examples are provided that make use of the HTML formatting package. These are shown in this section.
Table Formatting
A first simple example is Table.jsp, the source for which is available in WolframWebEngine/Examples/HTML. If you installed the Wolfram Web Engine web app as described previously, you should be able to connect to it via http://localhost:8080/webengine/Examples/HTML/Table.jsp. (You may have some other URL for accessing your server.)
A second example is RegressTable.jsp, the source for which is available in WolframWebEngine/Examples/HTML. If you installed the Wolfram Web Engine as described previously, you should be able to connect to it via http://localhost:8080/webengine/Examples/HTML/RegressTable.jsp. (You may have some other URL for accessing your server.) A section of the contents is shown here:
<msp:evaluate>
data = {{0.055, 90}, {0.091, 97}, {0.138, 107},
{0.167, 124}, {0.182, 142}, {0.211, 150},
{0.232, 172}, {0.248, 189}, {0.284, 209},
{0.351, 253}};
data = Map[# + {0, Random[Real, {-20, 20}]}&, data];
lm = LinearModelFit[data, {1, x^2}, x];
</msp:evaluate>
<msp:evaluate>
HTMLTableForm[MSPShow[ListPlot[data, Frame -> True, Axes -> False]],
TableHeadings -> {"Data to be fitted"},
TableAttributes -> {"cellpadding" -> "0", "cellspacing" -> "0"}
]
</msp:evaluate>
<msp:evaluate>
HTMLTableForm[
HTMLTableForm[lm["ParameterTableEntries"], TableAttributes -> {"cellpadding" -> "0", "cellspacing" -> "0"}],
TableAttributes -> {"cellpadding" -> "0", "cellspacing" -> "0"}, TableHeadings->{"ParameterTable"}
]
</msp:evaluate>
This shows how the packages are loaded. Note how the subpackage must be loaded as well. The data is assigned (typically, this would be loaded in some dynamic fashion), and the regression analysis is carried out. Two uses of HTMLTableForm then follow. In the first, the result of MSPShow is put into a table with a heading. This is a convenient way to attach a border and heading to something. In the second, the parameter table, pTable, is put into a table. This table is itself put into another table to get a heading.
Select Formatting
An example of the use of HTMLSelect is in Select.jsp, the source for which is available in WolframWebEngine/Examples/HTML. If you installed the Wolfram Web Engine web app as described previously, you should be able to connect to it via http://localhost:8080/webengine/Examples/HTML/Select.jsp. (You may have some other URL for accessing your server.) The source is shown here:
<msp:evaluate>
days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
day = Null;
If[MSPValueQ[$$daySelected],
dayPT = MSPToExpression[$$daySelected];
day = Part[days, dayPT]
];
</msp:evaluate>
<form action="Select.jsp" method="post">
<msp:evaluate>
HTMLSelect[days, daySelected, SelectedOptions -> day]
</msp:evaluate> <br/>
<input type="image" name="btnSubmit" src="../../Resources/Images/Buttons/evaluate.gif"/>
</form>
<msp:evaluate>
If[day =!= Null,
dayPT = Mod[dayPT + 1, 7, 1];
"The day after the day selected is " <> Part[days, dayPT] <> "."
]
</msp:evaluate>
In this example, the input parameter $$daySelected is inspected and used to determine which day was selected. The second evaluation actually puts down the select tag, showing how easy this is. The last evaluation computes the day after the day selected by incrementing the dayPT variable and then takes its modulus with respect to 7 with an offset of 1.
Using Java APIs
The purpose of the Wolfram Web Engine is to allow Wolfram Language computations to be run by a web server. These computations will typically involve one of the many tasks for which Wolfram Language is well suited, such as numerical or symbolic computation. However, sometimes it is useful in a Wolfram Web Engine computation to call outside of Wolfram Language to gain some extra functionality. The most convenient way to do this is to make use of Java. Regular interactive Wolfram Language can call to Java very easily with the J/Link toolkit, and the Wolfram Web Engine can do the same. More information on the concept of working with Java APIs and referencing Java objects from within Wolfram Language can be found in the J/Link documentation.
In the Wolfram Web Engine, two classes of calls can be distinguished: those to server-related APIs and those to more general Java APIs. These are discussed in the following two sections.
Server APIs
Calls to server-specific APIs that govern the operation and details of a particular Wolfram Web Engine site are facilitated by definition of the following server objects:
$ServletRequest | HTTPServletRequest object for this request |
$ServletResponse | HTTPServletResponse object for this request |
These are all Java object references maintained by J/Link and can be used in the typical J/Link fashion. $ServletRequest holds a reference to the servlet HTTPServletRequest object and $ServletResponse holds a reference to the servlet HTTPServletResponse object. The various methods for these objects are documented as part of the servlet API and will be found in any reference to servlets. For example, the request object has a method getRemoteAddr, which can be used in an MSP as follows:
<msp:evaluate>
$ServletRequest@getRemoteAddr[]
</msp:evaluate>
This will return the IP address of the client that sent the request and is equivalent to the CGI variable REMOTE_ADDR.
A more elaborate example is found in Request.jsp, the source for which is available in WolframWebEngine/Examples. If you installed the Wolfram Web Engine as described previously, you should be able to connect to it via http://localhost:8080/webengine/Examples/Request.jsp. (You may have some other URL for accessing your server.) This example extracts names and values from the HTTP request.
Note that any Java object references created when processing a particular page will be released when the whole page finishes. Note that Java objects created during initialization of the kernel will not be removed, providing a mechanism to maintain Java objects that persist from one call to another. Despite the fact that Java objects are automatically released, it is strongly recommended that all Java objects are either created inside of a call to JavaBlock or use ReleaseJavaObject explicitly. You can learn more about JavaBlock and ReleaseJavaObject in the J/Link documentation.
Other Java APIs
There are many other Java APIs that can be used by the Wolfram Web Engine. These include APIs for database connectivity, XML processing, speech generation, data format I/O and calling via HTTP to other web services. All of these are readily available to the Wolfram Web Engine. For more information, read the appropriate Java reference.
Data Loading and Computation
Wolfram Language contains a variety of data-loading functions, available through the function Import. This supports many formats, such as comma and tab-delimited text data, as well as more specialized formats for graphics, science, sound and XML. In addition, binary data can be loaded using the function Experimental`BinaryImport. If you find that your particular data is not well supported directly by Wolfram Language, you may use a Java API to load the data, which was described in the previous section.
In order to develop data-loading technology, it is a good idea to work in interactive Wolfram Language so that you understand how the data-loading functions work. When you have done this, you can add data loading to your web applications. At this point, you need to determine the source for your data. The following sections discuss some of the possibilities.
File I/O
If your data files are available to the file system of the computer on which your Wolfram Web Engine server runs, they can be read with a command like Import. For this to work, the name and location of the data file must be specified. This can be done in several ways. One involves placing the files into a directory and setting the full pathname of this directory. However, this method suffers from the extreme disadvantage that if you change the name of the directory, you will have to modify all your scripts that use this name. An improvement can be obtained by setting the name of the directory with an initialization parameter. This can be done in MSPConfiguration.xml with the parameter KernelInitializationCode, as shown in the following:
<KernelInitializeCode>
MyApplication`DataDirectory="C:\\Work\\Data"
</KernelInitializeCode>
This assigns the Wolfram Language symbol MyApplication`DataDirectory to "C:\Work\Data". Note the use of a full context name. This is necessary to prevent the symbol being cleared by the kernel-cleaning mechanism. This can then be loaded in a Wolfram Web Engine computation:
<msp:evaluate>
data = Import[ ToFileName[ MyApplication`DataDirectory, "file.dat"], "Table"];
</msp:evaluate>
An alternative is to place the data file into a directory that is on the Wolfram Language path setting $Path. This is the approach taken by the example Data1.jsp, which is shown in the following. Another alternative is to place the data file into the same directory as the script, and to use MSPPageDirectory:
<msp:evaluate>
data = Import[ ToFileName[MSPPageDirectory[], "file.dat"], "Table"];
</msp:evaluate>
This was used in the XML example Phone.jsp, which was discussed previously. It is particularly convenient to use MSPPageDirectory,since it means that data and scripts live in the same directory. Thus the entire web application can be moved from one server to another with a minimum of setting up. One disadvantage is that for JSPs, the data file can be loaded by a direct request to the server; thus it should only be used if there is no specialized information present in the data file. This might be the case if only certain information was suitable to be used in a response to each request.
HTTP Upload
Another way to load data into a Wolfram Web Engine server is to send it from the client machine with the HTTP request. The Wolfram Web Engine contains tools to support this with the function MSPGetUploadFile. This is demonstrated in the example, Upload.jsp, which is shown later.
Database Connectivity
DatabaseLink provides Wolfram Language with an industrial-strength, ready-made solution for integrating Wolfram Language with any standard SQL database. Integrated since Wolfram Language 5.1, it provides a convenient bridge between SQL databases and the Wolfram Web Engine.
DatabaseLink is based on Java Database Connectivity (JDBC) technology, and so it fits very well with the Java technology on which the Wolfram Web Engine is based. It has many useful and important features (listed here). One particularly useful feature for the Wolfram Web Engine is that DatabaseLink contains the HSQL database engine (HSQLDB), a lightweight database. This means that if you do not already have a database or want to experiment with using one, you do not have to set one up.
The Wolfram Web Engine contains two examples of working with a database. These are Database.jsp, which is accessible via http://localhost:8080/webengine/Examples/Database/Database.jsp, and DatabaseTable.jsp, which is accessible via http://localhost:8080/webengine/Examples/Database/DatabaseTable.jsp. Note that for these links to work, you need to have installed the Wolfram Web Engine and the DatabaseLink example databases, as described in its documentation. The example databases are installed into $UserBaseDirectory, so you need to make sure this is the $UserBaseDirectory for the user who is running the Wolfram Web Engine.
Web Services
Another way to find data for Wolfram Language is by contacting another website. A particularly convenient way to do this is if the other website provides the data as a web service. In this case, Wolfram Language can use the Web Services package to call the website and use its services.
Data Examples
The following is a collection of examples of the Wolfram Web Engine working with data.
Loading Data: Load.jsp
If you installed the Wolfram Web Engine as described previously, you should be able to connect to this JSP via http://localhost:8080/webengine/Examples/Data/Load.jsp. (You may have some other URL for accessing your server.)
This example shows how to load Wolfram Language packages and how to read a data file that is stored on the server. The data is processed with a data-smoothing algorithm, then a couple of plots are made. The source for this page is in WolframWebEngine/Examples/Data/Load.jsp. A section that shows the form tag is shown here:
<form action="Load.jsp" method="post">
<msp:evaluate>
data = Flatten[N[Import["Data/DataFile1.dat"]]];
term = 4;
If[MSPValueQ[$$term], term = MSPToExpression[$$term]];
</msp:evaluate>
Number of smoothing terms:
<input type="text" name="term" size="3" value="<msp:evaluate>MSPValue[$$term, "3"]</msp:evaluate>"/> <br/>
<input type="image" name="btnSubmit" src="../../Resources/Images/Buttons/evaluate.gif"/>
</form>
<msp:evaluate>
dataSmooth = MovingAverage[data, term];
MSPShow[ListPlot[{data, dataSmooth}, Joined -> {False, True}, ImageSize -> 600]]
</msp:evaluate>
In this example, an msp:evaluate tag loads the dataset Data/DataFile1.dat using the Import command. This will search for the data file on the Wolfram Language $Path and will find the Data directory inside the MSPScripts directory, which by default is located in WolframWebEngine/WEB-INF. It is worth looking inside your Wolfram Web Engine web application and confirming that you can locate the data file. The example then computes a moving average and plots the original and the smoothed data. This is all placed inside a form element so that it is possible to modify the number of terms.
One weakness of this example is that the data has to be loaded from the data file for every computation. It would be better to save the data somehow. In addition, it might be useful to allow the data to be uploaded from the client. These will be explored in the following sections.
Uploading Data: Upload.jsp
If you installed Wolfram Web Engine as described previously, you should be able to connect to this example via http://localhost:8080/webengine/Examples/Data/Upload.html. (You may have some other URL for accessing your server.)
This example allows the user to upload a data file and then retrieve the uploaded data. The data is then plotted. The source for this page is WolframWebEngine/Examples/Data/Upload.html and WolframWebEngine/Examples/Data/Upload.jsp. The contents of Upload.html are shown here:
<html>
<head>
<title>Uploading Data</title>
</head>
<body>
<h1>Uploading Data</h1>
<form method="post" enctype="multipart/form-data" action="Upload.jsp">
Enter a file to upload:
<input type="file" size="40" name="file"/> <br/>
<input type="image" src="../../Resources/Images/Buttons/submit.gif"/>
</form>
To generate suitable data,
<a href="DataGenerate.jsp">click here</a>
This example shows how data can be uploaded for processing by Wolfram Web Engine.
</body>
</html>
It should first be noted that this is an HTML page; it contains no Java or Wolfram Language inserts. A servlet container will deliver HTML pages just as it delivers JSPs, and they can all be put together in the same directories inside of the web app, which can also contain other files, such as those containing images or movies. This file contains a single form element that is set up to submit a data file using an enctype attribute of multipart/form-data and an input element of type file. When the Submit button is clicked, the form will be submitted along with the file to Upload.jsp. A selection of Upload.jsp is shown here:
<msp:evaluate>
file = "FileName" /. MSPGetUploadFile[];
data = Flatten[ N[ Import[ file, "Table"]]];
term = 4;
</msp:evaluate>
<msp:evaluate>
If[ StringQ[ file],
dataSmooth = MovingAverage[ data, term];
MSPShow[ MultipleListPlot[ data,dataSmooth,
PlotJoined ->{False,True},
SymbolShape -> Point,
SymbolStyle -> {{PointSize[0.008],Hue[0]}, {PointSize[0.001]}},
ImageSize -> 600]]]
</msp:evaluate>
In this selection, we see how the MSP function MSPGetUploadFile is used to retrieve the name of the data file by which the data has been stored on the server. This file name can then be used to read the data, as was done in the previous example, and the computation can proceed. It should be noted that this solution is somewhat limited; the data is only available once for one computation, and no facility has been added to change a parameter, for example, to control the data smoothing. For this, the data needs to be stored in a session variable. This is explored in the next example.
In this example, a test was made to determine whether the file name was in fact a string. This checks that a data file has, in fact, been uploaded. A file would not be uploaded if the page Upload.jsp was visited directly instead of coming from a request to Upload.html.
MSPGetUploadFile returns a list of useful information, including the file name that is used on the server, the original file name used on the client and the content type. In a case where there are multiple files to be uploaded, MSPGetUploadFile will throw an exception. If you wish to upload more than one file, you can use MSPGetUploadFileList.
Session Storage of Data: Session.jsp
If you installed Wolfram Web Engine as described previously, you should be able to connect to this JSP via http://localhost:8080/webengine/Examples/Data/Session.html. (You may have some other URL for accessing your server.)
This example allows the user to upload a data file and then retrieve the uploaded data. The data is stored in an HTTP session and then accessed from a separate page. The data is then plotted. The source for this page is WolframWebEngine/Examples/Data/Session.html, WolframWebEngine/Examples/Data/Session.jsp and WolframWebEngine/Examples/Data/SessionProcess.jsp. The contents of Session.html are shown here:
<html>
<head>
<title>Data in HttpSessions</title>
</head>
<body>
<h1>Data in HttpSessions</h1>
<form method="post" enctype="multipart/form-data" action="Session.jsp">
Enter a file to upload:
<input type="file" size="40" name="file"/> <br/>
<input type="image" src="../../Resources/Images/Buttons/submit.gif"/>
</form>
To generate suitable data,
<a href="DataGenerate.jsp" target="_blank">click here</a>
This example shows how data can be stored in HttpSessions for processing by Wolfram Web Engine.
</body>
</html>
This is very similar to Upload.html, except that it calls the JSP Session.jsp when the form is submitted. Session.jsp is shown here:
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>
<msp:evaluate>
file = "FileName" /. MSPGetUploadFile[];
data = Flatten[N[Import[file, "Table"]]];
MSPSessionVariable[UploadedData, Null];
UploadedData = data;
</msp:evaluate>
<jsp:forward page="SessionProcess.jsp" />
This short JSP reads the data that was uploaded, then uses MSPSessionVariable to store the data in a session variable named UploadedData. This is a very convenient way to store data persistently from one HTTP request to another. The data is actually stored in the server, so that even if the Wolfram kernel was restarted, the data would still be available. The storage uses what is known as an HTTP session and the server may use cookies or some other mechanism to actually store the data. This is how a shopping cart in an e-commerce website works. As far as a developer of an MSP website is concerned, it is all very simple: just use the function MSPSessionVariable, giving it the name of the variable and an initial value. After the data has been read, there is a jsp:forward to the page that actually does the computations and plots, SessionProcess.jsp. Often, it is a very good design principle to divide the code over a number of separate pages that all do different tasks; if you develop pages that have large amounts of complicated code in them, then refactoring might improve your system. A selection of Session.jsp is shown here:
<form action="SessionProcess.jsp" method="post">
Number of smoothing terms:
<input type="text" name="term" size="3" value="<msp:evaluate>MSPValue[$$term, "3"]</msp:evaluate>" /> <br/>
<input type="submit" name="btnSubmit" value="Evaluate"/>
</form>
<a href="Session.html">Load another data file?</a>
</div>
<div class="section">
<msp:evaluate>
MSPSessionVariable[UploadedData, Null];
term = 4;
If[MSPValueQ[$$term], term = MSPToExpression[$$term]];
</msp:evaluate>
<msp:evaluate>
If[UploadedData =!= Null,
dataSmooth = MovingAverage[UploadedData, term];
MSPShow[ListPlot[{UploadedData, dataSmooth},
Joined -> {False, True},
PlotStyle -> {{PointSize[0.008], Hue[0]}, {PointSize[0.001]}},
ImageSize -> 600
]]
]
</msp:evaluate>
SessionProcess.jsp is very similar to Load.jsp; the main difference is the line that obtains the data. Instead of reading data from a file, it uses the session variable UploadedData, which was assigned to the data in the previous JSP, Session.jsp. If, by some chance, UploadedData was not previously defined, as might happen if SessionProcess.jsp is visited directly, then UploadedData will have the value Null. Here, this just prevents any plot from being produced, but in general it might be used to transfer to an error page.
A further change to this section might be to store the data permanently on the server. For a simple data file, this could easily be done by using Wolfram Language file output operations. A more sophisticated application could use Java database connectivity to store the data and certain related information.
Session variables are discussed further in Advanced Topics: Variables.
Database Connections: Database.jsp
If you installed Wolfram Web Engine as described previously, you should be able to connect to this JSP via http://localhost:8080/webengine/Examples/Database/Database.jsp. (You may have some other URL for accessing your server.)
This example shows how to use DatabaseLink to connect to an SQL database. The database in question is one that is contained in HSQLDB, and for it to work, the sample databases need to be installed. This is described in the documentation. The databases are installed into $UserBaseDirectory, and so you need to make sure this is the $UserBaseDirectory for the user who is running the Wolfram Web Engine.
This example shows how you can open a connection to a database and make a query to a particular table based on an input parameter. The data is displayed with HTMLTableForm:
<form action="Database.jsp" method="post">
Lower limit:
<input type="text" name="limit" size="24" value="<msp:evaluate>MSPValue[$$limit, "6000"]</msp:evaluate>"/> <br/>
<input type="image" name="submitButton" src="../../Resources/Images/Buttons/search.gif"/>
</form>
<msp:evaluate>
Needs["DatabaseLink`"];
</msp:evaluate>
<msp:evaluate>
limit = 6000;
If[MSPValueQ[$$limit],
limit = MSPToExpression[$$limit]
];
</msp:evaluate>
<msp:evaluate>
conn = OpenSQLConnection["publisher"];
headings = {"TITLE_ID" , "LORANGE", "HIRANGE", "ROYALTY"};
data = SQLSelect[conn, {"ROYSCHED"}, headings, SQLColumn["LORANGE"] > limit];
</msp:evaluate>
<h3>
Royalty Schedule Table
</h3>
<msp:evaluate>
HTMLTableForm[data, TableHeadings -> headings, TableAttributes -> {"cellpadding" -> "0", "cellspacing" -> "0"}]
</msp:evaluate>
<!--
The shutdown command is specific to the HSQL database that
is used for these examples.
-->
<msp:evaluate>
SQLExecute[conn, "SHUTDOWN"];
CloseSQLConnection[conn];
</msp:evaluate>
The code loads DatabaseLink and carries out some processing of an input variable, which is used to select data from the database. It opens a connection to the database and selects data using the input variable and then formats and prints the result. Finally, it shuts down the database and closes the connection. The shutdown instruction is specific to HSQLDB and is necessary to make sure that the database can be used if the server is restarted.
Wolfram Language Packages and Applications
MSP provides a way to embed Wolfram Language code inside HTML. If the amount of code is significant, it might be more convenient to place the code into a Wolfram Language package and then refer to the package. In addition, a script might be needed to make use of existing Wolfram Language packages or applications. This section discusses how to work with Wolfram Language code and packages.
Loading Packages
It is relatively easy to add code that loads a package. Here is a simple example:
<%@ page language="java" %>
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>
<html>
<head>
<title>Live 3D Plotting</title>
</head>
<body text="#171717" bgcolor = "#ffffff">
<html>
<head>
<title>ConvexHull Computation</title>
</head>
<body bgcolor="#FFFFFF">
<h1>ConvexHull Computation</h1>
<msp:evaluate>Needs["ComputationalGeometry`"]; </msp:evaluate>
<msp:evaluate>ConvexHull[ {{1,5},{4,1},{10,2},{5,4}}]</msp:evaluate>
</body>
</html>
Notice how the evaluate tag uses Needs to load the package. An alternative but less desirable way to load a package is with Get. This is much less efficient since the package will be loaded each time the page is loaded. When Needs is used, the package is only loaded the first time.
An important detail is that one tag loads the package and another uses a function from the package. A tag that loads a package should not use functions that come from the package. If this happens, a shadowing symbol is created, which will mask the function you wish to use. When a shadowing symbol is created, a warning message is issued; the text of messages can be obtained with MSPGetMessages. It will also be displayed in the log files if verbose logging is enabled. The sections on logging and the kernel monitor discuss verbose logging and log files.
Sometimes, it is inconvenient to use two tags. In this case, you should use the fully qualified name for a function:
<msp:evaluate>
Needs["ComputationalGeometry`"];
ComputationalGeometry`ConvexHull[ {{1,5},{4,1},{10,2},{5,4}}]
</msp:evaluate>
A final issue concerns the use of subpackages. This can be an issue with Wolfram Language applications, which break up their implementation around a number of subpackages. For example, the following two fragments show a main package with context Main` and a subpackage with context Main`SubUnit`:
BeginPackage[ "Main`", {"Main`SubUnit`"}]
…
EndPackage[]
BeginPackage[ "Main`SubUnit`"]
MyFunction::usage = "MyFunction is in context Main`SubUnit`"
…
EndPackage[]
Both packages are loaded when the main package is loaded, as in the following.
Note that the MyFunction function is defined in the Main`SubUnit` context:
The implication for MSP coding is that a Needs statement is required for all the contexts that contain symbols you wish to use directly inside evaluate tags. Thus, if you wish to use MyFunction, you must insert a Needs statement for the Main` application and also for the context that contains the MyFunction function:
<msp:evaluate>
Needs["Main`"];
Needs["Main`SubUnit`"];</msp:evaluate>
<msp:evaluate>
MyFunction[ arguments]</msp:evaluate>
If you feel that packages are not being used correctly, it is a good idea to check that the contexts for symbols you are using have Needs statements. One way to check this is to write a small page that checks the contexts of functions you are using:
<msp:evaluate>
Needs["Main`"];
Needs["Main`SubUnit`"];</msp:evaluate>
<msp:evaluate>
Context[ MyFunction]</msp:evaluate>
If you have installed the application and run this script on your server, you should see Main`SubUnit` returned. This confirms that you have correctly loaded the function from the application.
Similar issues apply if you use the Master mechanism to load packages. You will either require a Needs statement for the individual contexts or refer to the full context name of the symbols. Of course, the former renders the Master mechanism not useful. An example of using full contexts is shown here:
<msp:evaluate>
Needs["Graphics`Master`"];</msp:evaluate>
<msp:evaluate>
color = Graphics`Color`Red </msp:evaluate>
Writing Packages
If you write any significant amount of your own code, it is a good idea to write it as a Wolfram Language package and load it into the Wolfram Web Engine. This is particularly important for the Wolfram Web Engine since you want to reduce the amount of Wolfram Language code that you have in your MSP pages. There are a number of references that help with the process of writing a package, for example, the section Setting Up Mathematica Packages. Instructions on how to load the package are given in the previous section; information on the location in which to place your package given in the following section.
If you do not use the Wolfram Language package format but instead use global definitions for your code, then you will need to load it every time the script is accessed. This is because of the postprocessing that takes place when a script is accessed. It is recommended that you place code into a Wolfram Language package.
Installing Packages
When a package of Wolfram Language code is available, it must be installed in some location so that it can be used by the Wolfram Web Engine. There are a number of ways this can be done; they are covered in the following sections.
Wolfram Web Engine Applications
The Wolfram Web Engine provides an Applications directory, located in WolframWebEngine/WEB-INF/Applications, which can be used for adding packages and applications. Any resources that are added in this location will only be available to the Wolfram Web Engine.
$BaseDirectory
The directory $BaseDirectory is provided to install resources such as packages and applications so that they are available to all users of Wolfram Language and all installations of the Wolfram Engine on a machine. Packages and applications can be installed in $BaseDirectory/Applications, where they will be available to the Wolfram Web Engine.
$UserBaseDirectory
The directory $UserBaseDirectory is provided to install resources such as packages and applications so that they are available to a particular user of Wolfram Language on a machine. Packages and applications can be installed in $UserBaseDirectory/Applications, where they will be available only to the particular user who is running the Wolfram Web Engine server.
The Script Directory
Another location for packages and applications is in the directory in which the JSP script lives. By default, files cannot be loaded from this directory. It is possible to add the location to the Wolfram Language path using MSPPageDirectory. This is demonstrated here, using Needs to load a package and Get to load a data file:
<msp:evaluate>
Block[{$Path=Append[$Path, MSPPageDirectory[]]},
Needs["MyPackage`"];
Get["Data.m"];
]
</msp:evaluate>
This arrangement allows the directory of JSPs and code to be moved to another installation of the Wolfram Web Engine with a minimum of rearrangement.
A drawback to this technique is that the code, MyFile.m, is available to be downloaded from the web server by a direct request. If it contains private information, this could be considered a security risk.
$TopDirectory
It is possible to install packages and applications inside the Wolfram Language layout. This makes them only available to that particular installation of Wolfram Language. Generally, this is not recommended.
Absolute File Name
A final way of installing code is to use an absolute pathname. An example is the following:
<msp:evaluate>Get[ "d:\\My Work\\LastOneThatWorked\\MyFile.m"]</msp:evaluate>
This type of loading is very common and is nearly always a very bad idea. It leads to fragile code that requires a significant amount of maintenance. For very little extra effort, one of the other methods that has been described should be used.
Extended Page Language
MSP provides a number of extended ways for a server computation to direct the contents of the resulting webpage. These are in addition to the basic tags, such as evaluate.
Expression Language
MSP support for the expression language gives a more concise way to call to Wolfram Language than typically done in the evaluate tag. It is also much more suitable to be nested inside another tag or an attribute.
<input type="text" name="fun" size="24"
value = "${msp:evaluate(' MSPValue[ $$fun, \"Sin[x]^2\"]')}">
The expression language form of evaluate is more concise and neater than the alternative version that relies on nesting an evaluate tag:
<input type="text" name="fun" size="24" value =
"<msp:evaluate> MSPValue[ $$fun, "Sin[x]^2"] </msp:evaluate> "
>
The expression language is particularly useful for working with the standard tags.
JSP Standard Tags
The Java Server Pages technology, on which MSP is based, provides a number of libraries of standard tags for carrying out a variety of useful purposes, such as controlling flow within the webpage. The libraries for these tags are included with the Wolfram Web Engine. If you want to use them, you must include an extra declaration at the top of your webpage:
if
The if tag is useful for conditionally adding a section of a webpage. An example is JSTLif.jsp, found in the Wolfram Web Engine web application in the directory Examples/ExtendedLanguage (the full path in Tomcat is webapps/WolframWebEngine/Examples/ExtendedLanguage). Some of the contents are shown here:
<c:if test="${msp:evaluate('MSPValueQ[$$test]')}">
<p>
The input variable had a value: ${msp:evaluate('$$test')}.
</p>
</c:if>
<c:if test="${msp:evaluate('!MSPValueQ[$$test]')}">
<p>
The input variable did not have a value.
</p>
</c:if>
In this example, if the input parameter $$test has a value, then the contents of the first if are included in the output page; this also shows the value of the parameter. On the other hand, if the parameter does not have a value—for example, if this is the first request—then the contents of the second if are included in the output page.
set
The set tag is a convenient way to store a result that can be used in other locations. An example is JSTLset.jsp, found in the Wolfram Web Engine web application in the directory Examples/ExtendedLanguage (the full path in Tomcat is webapps/WolframWebEngine/Examples/ExtendedLanguage). Some of the contents are shown here:
In this example, if the variable id is initialized with the result of a Wolfram Language computation. This is then used in a number of other instances of the expression language.
choose/when/otherwise
The choose, when and otherwise tags are another way to conditionally add blocks of text. An example is JSTLchoose.jsp, found in the Wolfram Web Engine web application in the directory Examples/ExtendedLanguage (the full path in Tomcat is webapps/WolframWebEngine/Examples/ExtendedLanguage). Some of the contents are shown here:
<c:set var="id" value="${msp:evaluate('$$test')}" />
<c:choose>
<c:when test="${id == 'Sin'}">
<p>Sin was chosen</p>
</c:when>
<c:when test="${id == 'Cos'}">
<p>Cos was chosen</p>
</c:when>
<c:when test="${id == 'Tan'}">
<p>Tan was chosen</p>
</c:when>
<c:otherwise>
<p>Something else was chosen</p>
</c:otherwise>
</c:choose>
In this example, the variable id is initialized with the result of a Wolfram Language computation. This is then used in a number of different when or otherwise tags. The final page depends on what was stored in the input parameter.
Queueing of Long Calculations
The standard usage of the Wolfram Web Engine carries out calculations inside of a single HTTP request. Wolfram Language can do a tremendous amount during an HTTP request, and many interesting websites can be built. However, if you want to run longer calculations that take more time than a typical HTTP request—for example, a calculation that takes 20 minutes—this cannot be done with the standard usage.
When the evaluateQueued tag is processed, the Wolfram Web Engine creates a job object that waits in a queue until a kernel is available to do the calculation and the HTTP request returns immediately, likely before the computation has even started. At some time in the future, the request is run and any results are saved. The web client can make a request to the server, using an identifier for the job, at any time to find out what has happened to the request.
The Wolfram Web Engine contains a simple example of the queueing system. The source for this can be found in the Wolfram Web Engine web application in the directory Examples/Queueing (the full path in Tomcat is webappls/WolframWebEngine/Examples/Queueing). There are three files, Start.jsp, which sets up parameters for the calculation; Submit.jsp, which actually submits the calculation to the queue; and Result.jsp, which waits for and displays the result.
The basis of the queueing system is the evaluateQueued tag, which is used instead of the evaluate tag. An example of the tag is shown here:
The body of the tag contains the long running calculation, in this case longCalculation[]. Note that if you load any package in this body, you will need to refer to the fully qualified name; this is discussed in more detail in the section Loading Packages. An alternative would be how to use the KernalInitializeCode configuration parameter to load any necessary packages.
The evaluateQueued tag actually creates a job object and places it into a queue. The job has an ID that can be used to work with it later, and this can be found with the var attribute. When the job actually runs, it uses the pool set by the pool attribute; if this is not found, then it will use the standard URL mapping used by the evaluate tag.
Attributes of the evaluateQueued tag.
The actual computation of the body of the evaluateQueued tag proceeds very similarly to the evaluate tag. The computation can make use of many of the MSP functions, for example saving image files and constructing URLs. It also has access to all the request parameters that came with the request. However, it does not have access to an HTTP request object, so it cannot make use of an HTTP session.
Interacting with the Queue
One key way that you can interact with the queue is using the var attribute of the evaluateQueued tag. This can be passed around the various webpages you want to work with, either as a request parameter or by saving in an HTTP session. An example, which starts a calculation and then offers a link to another page passing the var as a request parameter, is shown here:
<msp:evaluateQueued pool="General" var="id">
longCalculation[]
</msp:evaluateQueued>
<p>Get results <a href="Result.jsp?id=${id}">here</a>.</p>
The var attribute is actually a variable that holds a reference to the ID of the job object. MSP offers an expression language function that helps to find the job:
There are a number of things you can do with the job object. You can find out its state, whether it has started, finished, etc. You can find out its input as well as the result, if it has finished. You can also cancel the job.
It is also possible to access the job object via the Wolfram Language syntax. When the kernel is initialized, the symbol MSP`Utility`$Job is assigned to the job. Some functions for working with the job in both the expression language and Wolfram Language are shown here:
expression language syntax | Wolfram Language syntax | |
state of the job | ${job.state} | job@getState[] |
result of the computation | ${job.output} | job@getOutput[] |
ID of the worker | ${job.id} | job@getId[] |
Some techniques for the job object.
The state property of the job object shows you what state it is in. The possible values are shown here:
state values | meaning |
NEW | the job has been created |
QUEUED | the job is waiting in the queue |
RUNNING | the job is running |
TERMINATED | the job has terminated |
Values of the var property of the Job object.
The errorType and errorText properties of the job object show you information about the error state of the job. The possible values are shown here:
Values of the errorType property of the Job object.
If the state is TERMINATED, you can extract the result and know that the job has finished the computation.
For example, the Result.jsp page has code that looks like the following:
<c:set var="queues" value="${applicationScope['com.wolfram.msp.JobQueueMap']}"/>
<c:set var="queue" value="${queues[param.name]}"/>
<c:set var="job" value="${queue.jobs[param.id]}"/>
<msp:constantsMap className="com.wolfram.kerneltools.state.State" var="State"/>
<c:choose>
<c:when test="${empty job}">
Job with Id ${param.id} not found.
</c:when>
<c:when test="${job.state == State.QUEUED}">
<p>The computation is queued until a kernel becomes available.</p>
<a href="Result.jsp?name=${param.name}&id=${param.id}">Check again?</a>
</c:when>
<c:when test="${job.state == State.RUNNING}">
<p>The computation is currently running.</p>
<a href="Result.jsp?name=${param.name}&id=${param.id}">Check again?</a>
</c:when>
<c:when test="${job.state == State.TERMINATED}">
Error text: ${job.errorText}<br/>
Error type: ${job.errorType}<br/>
<p>Here are some snapshots of the result.</p>
${job.output}
</c:when>
<c:otherwise>
Error with job ${job.id}
</c:otherwise>
</c:choose>
This shows how the job object is extracted from the request parameter, and how to get the state property. The page then returns different content depending on the value of the state.
Lifetime of a Queued Request
These are the steps in processing a queued request:
● A page that contains an evaluateQueued tag is processed. This creates a job object, chooses a kernel pool and submits the job to the job queue for that pool. The pool is chosen from the pool attribute or a URL pattern if there is no pool attribute. If there is a var attribute, it is bound to the ID of the job. The state of the job is NEW when it is created; this moves to QUEUED once it is queued. Any request parameters that are sent with the page are saved to be used when the computation is actually run.
● The request that contains the evaluateQueued tag returns to the client. This might contain a reference to the IS of the job.
● At some future time, a kernel in the pool becomes available. This kernel is acquired for the job. At this point, any KernelAcquireCode configuration will be called. The job changes state from QUEUED to RUNNING.
● The kernel executes the body of the evaluateQueued tag. It is subject to all the constraints and limits of executing commands in the Wolfram Web Engine. If one of these is exceeded, the computation will terminate and the errorType will be set to KERNELEXCEPTION. However, if the computation finishes normally, the errorType will be set to NOERROR and the result stored in the job.
Organizing and Configuring a Queued Pool
Any kernel pool can be used to run computations from an evaluateQueued tag. However, it is typically good practice to have a pool that is designated for queued computations. More information about kernel pools and how to set them up can be found in the section on kernel pools. Using a separate pool is advantageous because you can configure it in a way that is more useful for a queued computation. For example, you might want to increase the KernelTimeLimit parameter to some longer value. Most of the configuration parameters are useful for a queued computation; you can find out more about configuring the Wolfram Web Engine in the section on configuration. Another advantage of a separate pool for queued calculations is that you have a pool available for normal calculations.
PDF Documents
Wolfram Language provides a powerful medium for electronic technical documents. Wolfram Notebook documents can combine text, mathematics, computations, charts, visualizations and interactive elements suitable for many technical areas. The documents can be kept in notebook format and viewed with the Wolfram Language notebook front end; alternatively, they can be converted into a variety of other formats, such as PDF, PostScript or XHTML.
MSP can use these features to automatically generate technical reports.
One format that is very easy to generate is Wolfram Notebooks, and there are a number of MSP examples that work by returning Wolfram Notebooks to the client. One example is Content.jsp. Using Wolfram Notebooks has the advantage that the document can be worked on further after reaching the client. A disadvantage is that it requires the client to have access to an application that can read notebooks, such as the Wolfram Engine. Another alternative is to use PDF. This has the advantage that the vast majority of clients are set up to render PDFs.
Wolfram Language can now automatically convert notebook documents into PDF format. This section will explore how to generate PDF documents from MSP.
Generating a Wolfram Language Notebook
A common way to do this involves using Wolfram Language commands for generating notebooks. A sample function is shown here (taken from the source used by Content.jsp):
MakeNotebook[] :=
Developer`UseFrontEnd[
Module[ {nb, nbobj},
nb = NotebookCreate[] ;
NotebookWrite[ nb, Cell[ "A Dynamically Created Notebook", "Title"]] ;
NotebookWrite[ nb,
Cell[ "Converted to " <> $$button, "Subtitle"]] ;
NotebookWrite[ nb, Cell[ "The date is " <> ToString[ Date[]], "Text"]] ;
nbobj = NotebookGet[ nb] ;
NotebookClose[ nb] ;
nbobj]]
This sample shows how a notebook object is created with NotebookCreate, and then how the content is added with NotebookWrite. When the notebook is complete, a Wolfram Language expression holding the notebook is obtained with NotebookGet, and this is returned. In a real-life situation, the document can contain graphics, more text and some computations. The Wolfram Language documentation has much more information on the commands for generating notebooks.
A major advantage of working with Wolfram Notebooks like this is that they will take care of details, such as font selection, graphics and mathematics, without the author having to be very involved.
Converting to PDF
The Wolfram Language function ExportString can be used to convert a Notebook expression into a string that contains the PDF. When it runs in the Wolfram Web Engine, it needs to be wrapped with UseFrontEnd. An example of the conversion is shown here:
UseFrontEnd[ ExportString[ nb, "PDF"]]
You can read more about PDF generation in the format documentation.
Returning PDF
There are several ways to return non-HTML content from MSP. These are summarized in the section Returning General Content. One simple way is to embed a URL that will download the document in your result. This can be done with MSPURLStore, as shown in the following:
<msp:evaluate>
nb = MakeNotebook[];
pdf = UseFrontEnd[ ExportString[ nb, "PDF"]];
MSPURLStore[ pdf, "application/pdf", "notebook.pdf"]
</msp:evaluate>
An alternative is to return the result directly from the request, which can be done as follows. Note that the content type must be set in the page directive:
<%@ page contentType="application/pdf"%>
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>
<msp:evaluate>
nb = MakeNotebook[];
UseFrontEnd[ ExportString[ nb, "PDF"]
</msp:evaluate>
Yet another approach is to use MSPReturn. This is useful if your call is embedded inside some other programs, or if the result is not always a PDF (perhaps because of error handling):
<msp:evaluate>
If[ convert === "True",
nb = MakeNotebook[];
pdf = UseFrontEnd[ ExportString[ nb, "PDF"]];
MSPReturn[ pdf, "application/pdf"]]
</msp:evaluate>
Creating a PDF Example
This section describes an example that generates a notebook and converts it to PDF. For it to work, you need to install the PDF tools described in the previous section. If you installed the Wolfram Web Engine as described previously, you should be able to connect to this JSP via http://localhost:8080/webengine/Examples/PDF/Generate.jsp. (You may have some other URL for accessing your server.) The source is in WolframWebEngine/Examples/PDF/Generate.jsp. Here is the JSP source:
<form action="Generate.jsp" method="post">
<input type="image" src="../../Resources/Images/Buttons/generate.gif"/>
<input type="hidden" name="button"/>
</form>
<msp:evaluate>
Needs["ExampleUtilities`Content`"]
</msp:evaluate>
<msp:evaluate>
If[MSPValueQ[$$button],
nb = MakeNotebook["PDF"];
pdf = UseFrontEnd[ExportString[nb, "PDF"]];
MSPReturn[pdf, "application/pdf", "Generate.pdf"]]
]
</msp:evaluate>
This code loads a basic package for creating notebooks. This is done in a separate evaluate tag, as described in the section Wolfram Language Packages and Applications. It calls the function MakeNotebook, which generates a very simple notebook and converts this into a PDF. The string is returned to the client using MSPReturn.
Returning General Content
The typical result of a Wolfram Web Engine request is an HTML page, which might include references to images. The commands available for MSP are designed to make this type of request very convenient. However, it is also very useful to be able to return other formats, such as Wolfram Notebooks or TeX documents. Wolfram Language commands for generating these other formats are Export and ExportString. When these other formats are returned to a browser, it can often launch a helper application that provides special functionality for that format. This section discusses how to use MSP to return general content of different formats.
Direct Return
The simplest way to return a content type other than HTML is to write a page that only returns your data. If your data is static, you should insert it into the page. Alternatively, if it has to be generated each time by the Wolfram Engine, you should just have an evaluate tag that returns your data and not use any HTML markup. It is a good idea to set the content type at the top of the page. This technique can be useful for AJAX and web service interactions. An example follows:
<%@ page contentType="text/mathml"%>
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>
<msp:evaluate>
MSPFormat[ Integrate[ 1/(1-x^3),x], StandardForm, RawMathML]
</msp:evaluate>
An alternative to using a page directive is to use then option of MSPPageOptions. The following example demonstrates how this can be done:
<msp:evaluate>
MSPPageOptions[ ContentType -> "text/mathml"]
</msp:evaluate>
<msp:evaluate>
MSPFormat[ Integrate[ 1/(1-x^3),x], StandardForm, RawMathML]
</msp:evaluate>
It is probably more convenient to just use the page directory.
MSPReturn
When an MSP script evaluates MSPReturn, the processing of the script is terminated and the first argument is immediately returned. The second argument specifies the content type. In this example, a notebook object is returned, and the result is set to be application/mathematica:
Certain HTTP clients can use the content type to launch a helper application. However, some clients need a file name to be associated with the request. For this purpose, MSPReturn takes a third argument that sets the file name in an HTTP header. An example follows:
<msp:evaluate>
If[ format === Notebook,
MSPReturn[ data, "application/mathematica","notebook.nb"]];
</msp:evaluate>
However, for some HTTP clients, this has the undesirable effect of causing the client to display two Open or Save dialog boxes. Most clients work much better if the request for the script that contains the MSPReturn uses the filen ame with an appropriate extension. Since the extension for MSP requests has to end in .jsp, this is not possible. An alternative is to generate a URL that has the correct extension; this functionality is provided by MSPURLStore.
MSPReturn is useful when the commands are embedded inside an existing page and you just want to terminate processing the page and return the result. It is simpler to use the direct return technique, so this is preferred if it is possible.
MSPURLStore
MSPURLStore uses the mechanism that MSP provides for storing images generated by commands such as MSPShow. It actually stores its argument on the server and returns a URL that references the argument:
The URL is relative to the request that contained the MSPURLStore. It contains a unique identifier and a description of the content type. Since the server steadily deletes stored information on the server, the information will not remain on the server indefinitely. This mechanism is particularly useful for preparing input for plugins and applets.
MSPURLStore can also take a third argument to set the file name, which is put into the URL that is returned. For example, the filename of notebook.nb is set in this example:
Setting the file name can be helpful for the browser to choose the correct helper application. The example script Examples/ContentStore.jsp has an example of MSPURLStore.
MSPURLStore is useful as a way of returning content if you need a URL such as in a src attribute of an img tag. This can be useful when working with dynamic client technologies such as AJAX.
AJAX
AJAX is a collection of related web technologies that help to make interactive web applications. The term actually stands for Asynchronous JavaScript and XML, and is aimed at increasing responsiveness and interactivity of web material.
Using AJAX requires that you work with JavaScript and have some experience with the structure of an HTML document. However, it is quite straightforward to work with AJAX in MSP.
Time Example
The Wolfram Web Engine contains a simple example of working with AJAX. The source for this can be found in the Wolfram Web Engine web application in the directory Examples/AJAX (the full path in Tomcat is webapps/WolframWebEngine/Examples/AJAX). The two files are LoadDate.jsp, which contains the AJAX code to call to the server, and ReturnDate.jsp, which returns the result from the server. If your server is configured and running, you can test this example with the URL http://localhost:8080/webengine/Examples/AJAX/LoadDate.jsp. (You may have some other URL for accessing your server.)
LoadDate.jsp contains two sections, a JavaScript section and an HTML section. The JavaScript is as follows (in real usage, this would be better put into a js library file rather than directly into the webpage):
<script>
function loadDate( ) {
var xmlHttp;
try { // Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
if (xmlHttp.overrideMimeType) {
xmlHttp.overrideMimeType('text/plain');
}
}
catch (e) {
// Internet Explorer
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
alert("Your browser does not support AJAX!");
return false;
}
}
}
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4) {
var elem = document.getElementById("time");
elem.value = xmlHttp.responseText;
}
}
var fullDate = document.getElementById("fullDate").checked;
var url = "ReturnDate.jsp";
url=url+"?fullDate="+fullDate;
xmlHttp.open("POST", url, true);
xmlHttp.send(null);
}
</script>
The first part of this example involves obtaining an instance of an XMLHttpRequest object. In this example, the instance is called xmlHttp. Note how different techniques are used for different browsers.
The XMLHttpRequest object is a major part of AJAX; this allows the asynchronous interaction, set up by the onreadystatechange function. This is called when there is a change in the state of the HTTP request. The change that this example tracks is when the readyState goes to 4, which means that the request is complete. When this happens, the function takes the text in the response and inserts it into the time element of the webpage. The onreadystatechange function is called asynchronously at some time in the future when the HTTP request is complete. The details of how this is done is completely left up to the XMLHttpRequest object, which leads to a tremendous simplification for the AJAX programmer.
After the result handler is set up, the actual request is made. This is done by setting up the URL to call, which includes an input parameter taken from the value of the checkbox in the HTML. After the send call, the request is triggered.
The HTML part of the page is as follows:
<h1>
AJAXDemo
</h1>
<p>
A basic AJAX example.
</p>
Result: <input type="text" id="time" />
<br/>
<br/>
<p> Full Date: <input type="checkbox" id="fullDate" /></p>
<button onclick="loadDate()">Update</button>
Some of this is concerned with the content of the page, such as the title, while other parts work with the interactive content. Note the button element. When this is clicked, the loadDate() JavaScript function, seen previously, is called. This means that when you click the button, the time input field is updated with the result of the web request.
On the server, there is a different page, ReturnDate.jsp, which actually does the server work. It is quite simple:
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>
<msp:evaluate>
If[ $$fullDate === "true",
DateString[],
DateString[{"Hour", ":","Minute",":","Second"}]]
</msp:evaluate>
There is one evaluation carried out by the Wolfram Engine; this checks the setting of the fullDate input parameter (which came from the checkbox in the original webpage). It returns a string of the date.
Note how the page does not need any HTML formatting because the result is just a string that is used by the loadDate() JavaScript function. Also note how the page displayed in the browser does not change; only part of the page changes. This can help to improve performance, since less is transmitted. Also, it can improve appearance since the whole page does not flicker. Another benefit is that other effects can be added; for example, while the browser is waiting for the result to come back, it could do something to indicate that the page is waiting for something.
HTML Example
AJAX techniques are not limited to string results from the server. In fact, the server can return with many different types of formats, and these can be used to change the contents of the document in the browser. This example shows how the src attribute of an img tag can be changed.
The source for this example can be found in the Wolfram Web Engine web application in the directory Examples/AJAX (the full path in Tomcat is webapps/WolframWebEngine/Examples/AJAX). The two files are LoadImage.jsp, which contains the AJAX code to call to the server, and ReturnImage.jsp, which returns the result from the server. If your server is configured and running, you can test this example with the URL http://localhost:8080/webengine/Examples/AJAX/LoadImage.jsp. (You may have some other URL for accessing your server.)
First, this is the source of ReturnImage.jsp, which is similar to ReturnDate.jsp except that it returns an HTML fragment (this is done with MSPShow); it also sets the content type to be text/xml:
<%@ page contentType="text/xml"%>
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>
<msp:evaluate>
fun = If[ MSPValueQ[ $$fun] && $$fun =!= "",
MSPToExpression[ $$fun],
Sin[x]];
p = Plot[ fun, {x,0,10}];
MSPShow[p]
</msp:evaluate>
You can test this with the URL http://localhost:8080/webengine/Examples/AJAX/ReturnImage.jsp. You should see something like the following:
Thus the page returns a fragment of HTML, not a complete document. The JavaScript function takes this fragment and inserts it into the document.
Here is the JavaScript function in LoadImage.jsp. It is quite similar to LoadDate.jsp:
<script>
function loadImage( ) {
var xmlHttp;
try { // Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
if (xmlHttp.overrideMimeType) {
xmlHttp.overrideMimeType('text/xml');
}
}
catch (e) {
// Internet Explorer
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
alert("Your browser does not support AJAX!");
return false;
}
}
}
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4) {
var xmlData = xmlHttp.responseXML;
var imgNode = xmlData.getElementsByTagName('img')[0];
var srcAttr = imgNode.attributes.getNamedItem("src");
var srcTxt = srcAttr.nodeValue;
var elem = document.getElementById("image");
elem.src = srcTxt;
}
}
var fun = document.getElementById("fun").value;
var url = "ReturnImage.jsp";
url=url+"?fun="+fun;
xmlHttp.open("POST", url, true);
xmlHttp.send(null);
}
</script>
The main difference here is the function that takes the result. It takes this as XML and does some processing on the result to find the value of the src attribute, which it sets into an img tag present in the page.
The HTML part of the page is as follows:
<h1>
AJAX Image Demo
</h1>
<p>
A basic AJAX example that loads an image.
</p>
Function: <input type="text" id="fun" />
<br/>
<br/>
<img id="image" />
<br/>
<br/>
<button onclick="loadImage()">Update</button>
Some of this is concerned with the content of the page, such as the title, while other parts work with the interactive content. Note the img tag labeled image, which has its src attribute filled out by the JavaScript function when the HTTP call is finished.
One important point about this example is how the client-side JavaScript function can work with the XML. In this case, the XML is XHTML, but in general it might be any form of XML.
Web Services and XML Exchange
The AJAX model is quite close to a web service. In fact, the techniques for setting up an AJAX interaction, particularly on the server, are closely related to informal web services, which are discussed in a later section. There is also an example of an informal web service that uses AJAX.