what is xxm
xxm is an interface written with and based on Delphi that compiles HTML with embedded Delphi code into a library, ready to use either locally, in the xxm ISAPI extension or other configurations.
what does xxm stand for
extensible expandable modules... or transportable transformation modules... anyway something fancy like that.
how do I get started
use xxmProject.exe to start a new project in a directory. register the project with xxmLocalDev.dll to use Internet Explorer to browse to it. add pages by creating extra .xxm (and .xxmi) files to the directory.
There is also a step-by-step tutorial with screenshots that shows how it's done.
does an xxl module need to be an ActiveX/COM/OLE library
no, an xxl library doesn't have to contain a Type Library and export the default procedures that a ActiveX/COM/OLE library would.
has CoInitialize been called for the thread the page is built in
why does Context.SessionID generate an EXxmResponseHeaderAlreadySent exception
Context.SessionID was inteded to use in XxmProject.LoadPage, when a new session is started, a session cookie is set. When you don't use Context.SessionID from LoadPage, and use it later on, the SetCookie can't add to the response headers.
why do I get this error: Error: ',' or ';' expected but identifier 'xxmFReg' found
You need to end the list of units in a [[@Unit1,Unit2,]] section with a comma. This is because in proto/xxm.pas and proto/xxmi.pas templates, this section is inserted here:
uses SysUtils, [[UsesClause]] xxmFReg;
syntax requires a comma after each unit, so of you provide one or more units, you have to provide the closing comma.
is it better/faster/... to use Context.SendHTML whereever possible?
No. HTML is parsed into Context.SendHTML calls for you, and doesn't take as much time extra as it would take you to type the HTML in Delphi string syntax. By far. The compile time of both is virtually equal. The execution time is equal.
can I use SaveToStream on object to write to the Context directly
Not directly, but the public folder that holds the xxm.pas file defining the main xxm interfaces, also holds a file xxmStream.pas that defines a TxxmOutputStream object, that inherits from TStream and takes a IxxmContext pointer.
does xxm work with jQuery and prototype?
Yes. These are javascript libraries, and javascript is able to resolve relative URL's, even with an XmlHttpRequest. Prototype may need a minor tweak to work with the xxmLocal handler in InternetExplorer, since as a security measure the responseDocument property is undefined on non-http protocol handlers.
when using an AutoBuild handler, pascal compile errors get shown with the line-number of the parsed source file, not the xxm source file, how do I map between the two?
as of version, the xxm parser keeps line-number maps for each file, and AutoBuild handlers use these to replace the line number of the compiler output (shown between parentheses "()") with the corresponding line-number(s) of the xxm source file (shown between square brackets "[]"). Since several tags from different places in the xxm-sourcefile could end up on the same line (e.g. all [[@someunit,]] tags are added to the implementation uses clause) more than one xxm source line-number could be displayed.
why would I use Context.Include, when I can create a fragment and call its Build(Context,Self,[],[]); myself?
I'll give three good reasons:
Exception handling: xxm handlers keeps track of which fragment is building, and adapts the default exception display to display information about the fragment the exception occurred in.
Include depth checking: xxm handlers keep a count of 'include depth' and disallows includes beyond a certain depth, this protects you from 'include loops', a scenario that just might pop up when which fragment to include is getting a but elaborate.
Fragment registry: xxm handlers use the fragment registry (actually IxxmProject.LoadFragment) to get hold of a fragment object, and doing so allows the fragment registry to handle object-pooling and object-reuse (if you'd like, in fact you're free to choose the fragment registry implementation for an xxm project).
Then again, if you really don't care about the above, you're totally free to call TxxmFragment.Build yourself.
why does the Redirect method have a Relative:boolean parameter?
short story: to make you think. Long story: though it is theoretically possible to infer from a URL if it's relative or absolute, in most cases, whether it is or not, is fixed by design.
For example a page posted to by a form, uses something like Context.Redirect('Product.xxm?id='+IntToStr(id),true); to display the result, or a website that forwards to sites with absolute URL's from websites should use Context.Redirect(WebsiteUrlFromDB,false);. Also, there's always this thing called security. Providing a page that redirects to a URL posted over a request parameter, is considered a vulnerability, so prevent writing code like Context.Redirect(x,false) where x is taken from the request data.
why is there no IXxmParameter.AsBool or IXxmParameter.AsDate?
I couldn't decide on a default encoding for dates and booleans. For booleans I generally use b:=Context['b'].AsInteger<>0; and dates I pass either as an integer or double cast to and from a TDateTime
why does my website show a build failed error message on one page when I'm browsing to another page?
it's a side-effect of using a compiled library to run the website for you. If the auto-build fails (auto-build is triggered by any page-refresh to the site, even AJAX-calls and image-loads), the library isn't loaded and the build failed page is shown, for every request to the site. It's strongly advised to use a single instance of the website source-files to work on for each developer. If you work on the same set of files with a number of developer's, each build failed error caused by one developer will interrupt the testing of the other developers. (It's also strongly advised to use a version control system on the source-files between multiple developers. e.g. SVN or Git)
can I keep sending when a client disconnects
no. If Context.BufferSize is 0, Context.Send may throw an exception depending on which handler is used. Most handlers will throw an exception from deep within the underlying data transport system.
If Context.BufferSize is set to something more than 0, this exception will get thrown when the buffer is full, or when Context.Flush is called, and an attempt is made to transmit data.
If you want to maintain a long-running process with the client disconnected, check Context.Connected whether it is safe to send data.
(Though this will keep one of the threads in the thread-pool occupied and unavailable to process incoming requests.
For long-running processes please use threads you manage yourself, or use another server process with IPC like COM, named pipes or network connections.)
why do I get this error: There is no overloaded version of 'Send' that can be called with these arguments?
IXxmContext has a few overloads of Send and SendHTML so that in most cases you can use the [[=x]] syntax without much thinking about type, but some types are unclear or ambiguous between the available overloads. In this case use an explicit type cast or an extra local variable
how do I debug an xxm project
an xxm project is still a Delphi project, so you can open the project's dpr in Delphi, just remember to edit the xxm and xxmi files, and not the pas files directly (unless for temporary debugging behaviour).
When you're using xxmLocal (or xxmLocalDev), set the host application to Internet Explorer (typically C:\Program Files\Internet Explorer\iexplore.exe), optionally with an "xxm://" URL to open your project. (Update: to force IE8 to run in a single process, see TabProcGrowth)
When you're using xxmIsapiEx (or xxmIsapiDev) on your local IIS, switch IIS into stand-alone mode and use inetinfo.exe as host application, or create a virtual directory with high isolation (IIS 7: in an application pool of it's own), and use %SystemRoot%\system32\dllhost.exe /ProcessID:{AppID} with the AppID you can pick up from the properties of the COM+ application in the 'Component Services' administrative tool
how do I support passing extra parameters with the directory delimiter?
(e.g.: http://localhost/xxm/test/test.xxm/a/1/b/2 )
The URL is parsed to get a project name and a fragment address. no forward directory checking is done, since xxm files and directories may not be present, it's up to the project to provide a fragment or not for a fragment address. (xxmp.pas' TxxmProject.LoadFragment and the default xxmFReg.pas, see the 'URL Routing' demo in available for download)
why can't IE download files directly? I get this error:
Internet Explorer cannot download somefile.ext from site.
Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found. Please try again later.
the registry is used to determine which MIME-type to declare for the file. Look under HKEY_CLASSES_ROOT for a ContentType value under the key with the extension (e.g.: [HKEY_CLASSES_ROOT\.txt] @ContentType="text/plain")
is it possible to update an xxm project without taking the webserver/webservice down?
yes. When setting up an xxm environment, select one of the auto-update options (xxm*AU.*). These check the directory of the xxm project if a .xxu file is provided, then queues new requests until all current requests are completed, unloads the .xxl library, replaces it with the .xxu file, re-loads the library and continues processing requests.
how do I know if auto-update has updated my xxl?
you know because the .xxu file has been renamed to .xxl to replace the previous file. It is also recommended to have an internal version number display generated from code, somewhere in the project e.g. on an about page or on the page footer.
do I always need an xxm handler to run an xxm project?
while it is strongly advised to use the development handlers for development, and the auto-update handlers for the live environment, once you have an xxm project that is stable, you can make a 'skip the handler' build using xxmConv.exe and one of the alternative templates from the conv\proto_* folders. These combine xxm source with the generated source of the xxm project into a dedicated dll or exe.
why did you make another website development platform? think you could do better than the tried and tested ones out there?
*sigh* please read this: why