Macros - NXML

Requires Platform 4.2+

Using Parameters In Macros

Macros provide a way to associate a name with a group of valid Nexaweb page instructions (XUpdate, MCO, data, and so forth) that the Nexaweb platform loads into memory and executes at any time.

Nexaweb 4.2.x now allows you to use java.text.MessageFormat syntax to specify parameters in macros that execute logic, thus allowing macros to accept arguments. MessageFormat syntax allows you to specify where arguments go and the format of those arguments (such as a number format that includes comma separation, dollar signs, and so forth.)  The use of parameters in macros increases each macro's flexiblity, since you can now re-use each macro to act on a varying list of components. For example, with the use of parameters, you can write one macro to close two different windows rather than writing two separate macros (without parameters) to close those windows.

When used to develop client side logic, macros provide the following benefits:

  • Using the same XML-based tools that you use to develop your client UI
  • No roundtrips to the server required
  • Portability for future Nexaweb client environments

The following example shows use of a macro that does not use parameters:

Macro:

 

<modifications document=”nxml”>
<remove select="id(''{0}'')">
</modifications>

 

 
Calling this Macro:

The following example shows use of a macro with parameters:

Macro:

 

<modifications document=”nxml”>
             <remove select="id(''{0}'')">
 </modifications>

 

Calling this macro:

onCommand=”macro://mymacro.execute (‘Window1’)

Defining Macros Overview

The following shows the basic format for defining macros:

 

<macro xmlns:macro="http://nexaweb.com/macro">
   name = name-attribute-type
 (any valid Nexaweb elements or strings that become Nexaweb page elements when substituted for parameters)
 </macro>

 

name-attribute-type specifies a name that uniquely identifies this macro.

When defining macros keep in mind the following: 

  • Macro names must be unique. If you create a new macro with the same name as an existing macro, the new macro overwrites the old macro.
  • Nexaweb translates whatever Nexaweb page instructions you include in a macro into a string and formats it using java.text.message format, so the Nexaweb page instructions in your macro must conform to java.text.message format syntax, for example, to conform to java.text.message format syntax, you must escape single ticks and curly brackets in your Nexaweb page instructions.

Defining Macro XUpdate Commands Without Parameters

The following example shows a page containing a macro with an XUpdate command that does not use parameters.

In this example, a page contains a macro named, mymacro. The body of this macro contains just one XUpdate command (set-attribute) that changes the text of a label ("mylabel"). When a user presses the button "Execute Macro", the macro executes and changes the label's name from Old Text to New Text.

 

<nxml>
     <macro:macro name="mymacro" xmlns:macro="http://nexaweb.com/macro">
         <xu:modifications xmlns:xu="http://nexaweb.com/xupdate">
             <xu:set-attribute select="id(''mylabel'')">
                 <xu:attribute name="text" value="New Text" />
             </xu:set-attribute>
         </xu:modifications>
     </macro:macro>
    <panel>
         <flowLayout align="center"/>
         <label text="Old Text" id="mylabel" bgcolor="green"/>
         <button text="Execute Macro" onCommand="macro://mymacro.execute()"/>
     </panel>
 </nxml>

 

Defining Macro XUpdate Commands With Parameters

 The following examples show the same macro without and with parameters:

 

<macro:macro name="mydialog" xmlns:macro="http://nexaweb.com/macro">
      <xu:modifications document="nxml" xmlns:xu="http://nexaweb.com/xupdate">
         <xu:append select="/nxml/rootPane">
             <dialog title="My Dialog" closeable="false" focused="true" centered="true"> 
                 <label text="My dialog is your dialog, from California, to the New York islands"/>
             </dialog>
         </xu:append>
     </xu:modifications>
 </macro:macro>
<macro:macro name="generic-dialog" xmlns:macro="http://nexaweb.com/macro">
      <xu:modifications document="nxml" xmlns:xu="http://nexaweb.com/xupdate">
         <xu:append select="/nxml/rootPane">
             <dialog title="{0}" closeable="{1}" focused="{2}" centered="{3}"> 
                 <label text="{4}"/>
             </dialog>
         </xu:append>
     </xu:modifications>
 </macro:macro>

 

The following shows a macro call to the macro with parameters:

 

<macro:macroCall name="generic-dialog"
      xmlns:macro="http://nexaweb.com/macro" >
      <macro:parameter>ThisIt</macro:parameter>
      <macro:parameter>true</macro:parameter>
      <macro:parameter>true</macro:parameter>
      <macro:parameter>false</macro:parameter>
      <macro:parameter>Answer</macro:parameter>
 </macro:macroCall>

 

The following shows an event handler call to the macro with parameters:

 

<button onCommand="macro://generic-dialog.execute( 'ThisIt', 'true', 'true', 'false', 'Answer' )" />

 

Specifying Parameters In Macros

You specify macro parameters in Nexaweb instructions for attribute values using java.text.MessageFormat. (For more information on Java MessageFormat syntax, see: http://java.sun.com/j2se/1.4.2/docs/api/.)

Note: Java Virtual Machine (JVM) 1.4 or earlier limits the number of placeholders you can use in a marco. In later JVMs, you can specify an unlimited number of placeholders. See java.sun.com for more details on this limitation.

In MessageFormat syntax, a single tick ( ' ) character is a special character - used to specify a string literal that is ignored by MessageFormat. Therefore, in this format, when you want to use a single tick you must use two single ticks ( '' ) instead.

Note: You must use two single quote characters ' . A double qoute character  " does not work.

Thus, a Nexaweb instruction not used in a macro would appear as the first string in the following example, while the same Nexaweb instruction used in a macro would appear as the second string in this example:

id('mywindow')
id(''mywindow'')

You specify the actual value to replace the parameters, when the Nexaweb instruction executes, in macro or event handler calls.

You can specify two types of parameters in macros:

  • Static values specified as literals.
  • Dynamic values specified as XPath statements against a document.

Specifying Parameters In Event Handlers

 

<button onCommand="macro://generic-dialog( {id('myDialogTitleField')/@text}, 'true', 'true', 'false', {MyDataDocument:id('myTextField')/@text} )" />

 

Programatic Macro Definition and Call

The following example defines a macro programatically:

 

MacroContainer macroContainer = ClientSession.getMacroContainer();
 Macro macro = macroContainer.createMacro
      ("<xu:modifications xmlns:xu=\"http://nexaweb.com/xupdate\" document=\"nxml\">" +
       " <xu:append select=\"/nxml/rootPane[1]\">" +
       " <dialog>" +
       " <label text=\"Call me Ishmael. Some years ago- never mind how long precisely...\" />" +
       " </dialog>" +
       " </xu:append>" +
       "</xu:modifications>" );
 macroContainer.putMacro("nexaweb-examples-herman-melville-dialog", macro);

 

The following example shows a programatic macro call:

 

MacroContainer macroContainer = clientSession.getMacroContainer();
 Macro melvilleMacro = macroContainer.getMacro( "nexaweb-examples-herman-melville-dialog" );
 melvilleMacro.execute();
Macro genericXUpdateMacro = macroContainer.getMacro( "nexaweb-examples-generic-xupdate" );
 genericXUpdateMacro.execute( new Object [] { "remove-element", "id('anElementId')", "" } );

 genericXUpdateMacro.execute( new Object [] { "append", 
"/nxml/rootPane[1]", "<dialog><label 
text=\"Mylabel\"/></dialog>" } );

 

Debugging and Troubleshooting Macros
To debug macros, enable macro debug logging in the application's client configuration file, nexaweb-client.xml, as follows:

 

<log-configuration>
     <log name="Macro" log-level="debug"/>
 </log-configuration>

 

The following shows sample output from the macro log (note that all client side logging goes to the browser's java console):

Note: The sample output below shows the specified arguments, the macro, and pre- and post- formatting.

 

[Debug - 10:42:22 (Macro): Enabled debug logging.]
 [Debug - 10:42:35 (Macro): Formatting macro with 0 args: []]
 [Debug - 10:42:35 (Macro): Macro pre-formatting:
 <nxml><xu:modifications xmlns:xu="http://nexaweb.com/xupdate" document="nxml">
 <xu:append select="/nxml/rootPane[1]">
 <dialog>
 <label text="Call me Ishmael. Some years ago- never mind how long precisely..."/>
 </dialog>
 </xu:append>
 </xu:modifications></nxml>]
 [Debug - 10:42:35 (Macro): Macro post-formatting:
 <nxml>
 <xu:modifications xmlns:xu="http://nexaweb.com/xupdate" document="nxml">
 <xu:append select="/nxml/rootPane[1]">
 <dialog>
 <label text="Call me Ishmael. Some years ago- never mind how long precisely..."/>
 </dialog>
 </xu:append>
 </xu:modifications>
 </nxml>]

 [Debug - 10:42:46 (Macro): Formatting macro with 3 args: ["append", 
"/nxml/rootPane[1]", "<dialog><label text="Mylabel" 
/></dialog>"]]
 [Debug - 10:42:46 (Macro): Macro pre-formatting:
 <nxml>
 <xu:modifications document="nxml" xmlns:xu="http://nexaweb.com/xupdate" >
 <xu:{0} select="{1}" >
 {2}
 </xu:{0}>
 </xu:modifications>
 </nxml>]
 [Debug - 10:42:46 (Macro): Macro post-formatting:
 <nxml>
 <xu:modifications document="nxml" xmlns:xu="http://nexaweb.com/xupdate" >
 <xu:append select="/nxml/rootPane[1]" >
 <dialog><label text="Mylabel" /></dialog>
 </xu:append>
 </xu:modifications>
 </nxml>]

 

Backward Compatibility
If you were using macros prior to Nexaweb's 4.2 release and those macros contained any of the MessageFormat special characters, you may wish to disable the MessageFormat functionality to ensure that your macros continue to function as before. This can be done by changing the following value to true in your nexaweb-client.xml file:

 

<!-- This parameter is supplied so that the macro code can know NOT -->
<!-- to use MessageFormat for the macro strings. in 4.2 we added parameters -->
<!-- which use MessageFormat, thus single tick escaping is required in 4.2 -->
<!-- plus. We want existing macros to work if the customer so desires. -->
<ensure-pre-4-dot-2-macro-compatibility>false</ensure-pre-4-dot-2-macro-compatibility> 

 

onCommand=”macro://mymacro.execute (‘Window2’)"