Value Added Javascript
Kuali is using the DWR (Direct Web Remoting) toolkit provided by Getahead Limited. It is a Java library that allows "direct" invocation of Java methods and returning from their results to/from JavaScript. It is configured via XML files present in each module. (These XML files are referenced in web.xml. DWR runs as a Java servlet.)
DWR configuration XML file
The DWR configuration file for, e.g., module "foo" is work/src/edu/institution/kuali/module/foo/dwr-foo.xml
. If your module doesn't have one already, then you need to create it and add a reference to it in your module's KualiModule
bean, for example:
<property name="scriptConfigurationFilePaths"> <list> <value>edu/institution/kuali/module/foo/dwr-foo.xml</value> </list> </property>
If you are adding a DWR configuration file to a KFS built-in module, instead of changing the module bean definition that comes with KFS, create a new overriding Spring bean in a Spring bean file created by the institution. See the OJB documentation.
Creators
The first thing you need to add to your DWR configuration XML file is a creator. For reference, see /org/kuali/kfs/coa/dwr-coa.xml. These "expose" methods on Java classes to DWR JavaScript calls. It is possible to use wildcards, but specifying exact methods is probably safer. Creators also tell DWR how to obtain an instance of the given class. So far, all DWR calls are accessing services. So, DWR is able to pull beans out of the Spring ApplicationContext. Here is an example of the creator for the AccountService:
<create creator="spring" javascript="AccountService"> <param name="beanName" value="accountService" /> <include method="getByPrimaryIdWithCaching" /> </create>
The above snippet tells DWR to use "spring" for obtaining the object and pass into the creator a "beanName" of "accountService." This object will be exposed to JavaScript with the name "AccountService" and will support the one method "getByPrimaryIdWithCaching." DWR, at runtime, takes care of determining the parameters this method will expose.
You can list as many "include" methods as needed. See the DWR documentation on Creators for more information.
Converters
Converters are what allow DWR to handle complex objects. DWR comes with a standard set of converters which handle all the normal data types (including arrays and collections.) For Kuali BusinessObjects, you will need to add a converter which tells it what to do. You will likely need one of these for the return type of any method which does not return a type in java.lang or java.util. The standard type of converter you will need is a "bean" converter. It accepts a class name and a list of properties which should be exposed. Here is the converter for the Account BusinessObject:
<convert converter="bean" match="org.kuali.kfs.coa.businessobject.Account"> <param name="include" value="chartOfAccountCode,accountNumber,accountName,accountTypeCode,subFundGroupCode,organizationCode, financialIcrSeriesIdentifier, indirectCostRcvyFinCoaCode,indirectCostRecoveryAcctNbr,accountOffCampusIndicator,acctIndirectCostRcvyTypeCd" /> </convert>
The "match" attribute identifies the class to convert. (Again, wildcards are allowed, but should be avoided.) The "include" parameter is a comma-delimited list of the property names which should be returned when an object of this class is returned from a DWR exposed method call. The list of properties may also include attributes which are other business objects. In that case, you must also define a converter for that object's class as well.
For more information, see the DWR Documentation on Converters.
Using AJAX from Javascript
Including the Script Files
Before you can make the calls, you must include the JavaScript files which define the external representations of the services and their methods. The Creator definition tells DWR to create a generated JavaScript file accessible at a certain URL. There are also two support files that must be included. Here is the snippet to bring them in:
<script language="JavaScript" src="dwr/engine.js" type="text/javascript"></script> <script language="JavaScript" src="dwr/util.js" type="text/javascript"></script>
These are AUTOMATICALLY included in page.tag. So, for normal pages within the Kuali application, you will not need to include these files.
To bring in the service you just defined, you add a script line like:
<script language="JavaScript" src="dwr/interfaces/<Creator Name>.js" type="text/javascript"></script>
If using page.tag to render the page, a list of additional javascript files may be specified using the "additionalScriptFiles" attribute of the tag file.
Where <Creator Name> is the name you defined in the "javascript" attribute of the creator.
Including the Script Files in Maintenance Documents
For documents which don't have their own JSP files and are controlled by the Data Dictionary, you include the JS into your code by adding <webScriptFile> tags into the document data dictionary file. You will also want to include at least one additional file which holds the document-specific code which will call the DWR methods. Here is the code from AccountMaintenanceDocument.xml:
<bean id="AccountGlobalMaintenanceDocument" parent="AccountGlobalMaintenanceDocument-parentBean"/> <bean id="AccountGlobalMaintenanceDocument-parentBean" abstract="true" parent="MaintenanceDocumentEntry"> ...... <property name="webScriptFiles"> <list> <value>../dwr/interface/AccountService.js</value> <value>../scripts/coa/accountGlobal.js</value> <value>../scripts/sys/objectInfo.js</value> </list> </property> .........
Making the Asynchronous Call
These instructions are for making a one-off call for a particular document. If your method would be useful for other documents, consider putting it in that module's objectInfo.js file. (Which lives in work/web-root/scripts/<module ID>.)
Before calling the method, you need to construct an object which handles the results when they return. DWR calls are asynchronous, the call will not block until the method returns. Control is returned to the browser immediately. When DWR sends the results, is uses the given object to handle the results.
So, define a variable as follows:
var dwrReply = { callback:function(data) { // do something with "data" here }, errorHandler:function( errorMessage ) { // this is called if there is an error calling the method // or with the JavaScript in the above callback function } };
This defines an object with two properties, each a function. The "callback" function is called when the DWR call returns from the server. It will be passed the converted Java object for use by the method. Information in the data object is accessed just like JavaBean property notation. For Example, the account name would be accessed as "data.accountName" If you embed another business object into the class, you would access it like: "data.chartOfAccounts.finChartOfAccountDescription"
It's easiest to take a look at some of the existing methods in work/web-root/scripts/kfs/objectInfo.js to see how the data is used.
Now, to call the method, you make a call of this form:
AccountService.getByPrimaryIdWithCaching( coaCode, accountCode, dwrReply );
Where the first parameters are the actual parameters that the Java method requires. After all the normal parameters, you pass in the dwrReply object that you just created.
At this point, you would put the above code into a method and call that method from an appropriate place in the application (like an onblur handler.)
Making the Asynchronous Call from Maintenance Documents
Again, maintenance documents are a little different as you don't have direct access to the page to add a call to the JavaScript. But, there is a way to attach onblur handlers to fields from the data dictionary. To do so, you add the webUILeaveFieldFunction to the <maintainableField> tag. For example:
<maintainableField name="subFundGroupCode" required="true" webUILeaveFieldFunction="onblur_subFundGroup" />
This will call a JavaScript function and pass in a reference to the HTML form field. From that you can grab its value, other field's values, and whatever else you need to set up the call to the DWR function.
Kuali documentation is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.
Kuali software is licensed for use pursuant to the Affero General Public License, version 3.
Copyright © 2014 Kuali, Inc. All rights reserved.
Portions of Kuali are copyrighted by other parties as described in the Acknowledgments screen.
Kuali ® is a registered trademark of the Trustees of Indiana University.