In the previous installments we’ve seen how to store the JavaScript code in a database, and how to retrieve that code when starting our Java program. In this post we’ll look at the RunScript class that we use to execute the JavaScript, plus some of the Java-JavaScript interface elements.

If you recall from the previous installment, we execute the JavaScript as shown:

[java]
javax.swing.Action act = mainForm.getActionMap().get("AfterInsertPart");
if (act != null)
act.actionPerformed(new java.awt.event.ActionEvent(this, 0, "AfterInsertPart"));
[/java]

Where “AfteInsertPart” comes from our naming convention.

Without further ado, here’s a cut-down example of our RunScript class:

[java]
public class RunScript implements javax.swing.Action {
private MainForm mainForm = null;

/**
* string to run
*/
private String scriptLiteral = null;

/**
* Mime type of scripting language, so the correct scripting engine can be chosen
*/
private javax.activation.MimeType scriptLanguage = null;

/**
* Action is enabled
*/
private boolean enabled = true;

/**
* constructor
*/
public RunScript() {
}

/**
* Constructor when running a string
* @param scriptLiteral script to run
* @param scriptLanguage script Mime type
* @param orderForm The orderForm in which this component is embedded
*/
public RunScript(String scriptLiteral, javax.activation.MimeType scriptLanguage, MainForm mainForm) {
this.scriptLiteral = scriptLiteral;
this.scriptLanguage = scriptLanguage;
this.mainForm = mainForm;
}

/**
* Is action enabled
* @return true iff action is enabled
*/
@Override
public boolean isEnabled() {
return true;
}

/**
* control whether action is enabled
* @param enabled true to enable action
*/
@Override
public void setEnabled(boolean enabled) {
}

/**
* Listen for property changes
* @param listener Object to be notified when a property changes
*/
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
}

/**
* Remove a property change listener
* @param listener object to be removed
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
}

/**
* Given a key return the corresponding value
* @param key what to look up
* @return value for key
*/
@Override
public Object getValue(String key) {
null;
}

/**
* Add a value for a key
* @param key Used to look up the value
* @param value Associated with the key
*/
@Override
public void putValue(String key, Object value) {
}

/**
* Run the script
* @param evt Event that triggers this action
*/
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (scriptLiteral != null) {
javax.script.ScriptEngineManager semgr;
javax.script.ScriptEngine scriptEngine;
try {
semgr = new javax.script.ScriptEngineManager();
scriptEngine = semgr.getEngineByMimeType(scriptLanguage.toString());
if (scriptEngine != null) {
scriptEngine.put("output", System.out);
scriptEngine.put("order", mainForm.getScriptInterface());
scriptEngine.put("customer", mainForm.getCustomer().getScriptInterface());
scriptEngine.put("util", new Util().getScriptInterface(mainForm));
scriptEngine.eval(scriptLiteral);
}
}
catch (java.io.IOException e) {
Util.logException(e, "IO exception.");
}
catch (javax.script.ScriptException e) {
Util.logException(e, "Script exception.");
}
catch (java.lang.Exception e) {
Util.logException(e, "Exception while handling script.");
}
}
}
}
[/java]

I don’t believe I’ve chopped out anything vital. If I have please let me know and I’ll fix it.

As you see, this is a pretty standard implementation of a Swing Action object.

ScriptEngine.put() is what makes Java objects available in JavaScript.

ScriptEngine.eval() is what actually runs the JavaScript.

The various getScriptInterface() methods are my own convention, to isolate the JavaScript from changes in the Java code, and vice versa. When I build a Java class that I want to share, at least partially, with JavaScript, I’ll include a public class ScriptInterface with all the JavaScript accessors. For example:

[java]
public class Customer {
private int customer_ID;
private String paymentTerms;
public class ScriptInterface {
private Customer customer;
ScriptInterface(Customer customer) {
this.customer = customer;
}
/**
* Retrieve the customer number
* @return customer number
*/
public Integer getCustomer_ID() {
try {
return customer.customer_ID;
}
catch (java.lang.Exception e) {
System.out.println("Exception getting customer ID:" + e);
return "";
}
}
/**
* Retrieve the customer payment terms
* @return customer name
*/
public String getPaymentTerms() {
try {
return customer.paymentTerms.trim();
}
catch (java.lang.Exception e) {
System.out.println("Exception getting customer payment terms:" + e);
return "";
}
}
}

/**
* Retrieve an instance of the scripting interface
* @return An instance of the scripting interface
*/
public ScriptInterface getScriptInterface() {
return new ScriptInterface(this);
}
}
[/java]

So, if I want to pop open an alert box when an order is started for customer 123, I can write this JavaScript:

[javascript]
if (customer.getCustomer_ID()===123) {
util.alert("Boy howdy, here comes customer 123!");
}
[/javascript]

The “customer” object is shared from the Java line

[java]
scriptEngine.put("customer", mainForm.getCustomer().getScriptInterface());
[/java]

And the getCustomer_ID() method on the customer object is defined starting at the Java line

[java]
public Integer getCustomer_ID()
[/java]

I haven’t shown the util.alert method, that’s left as an exercise for the reader.

Well, that’s the heart of the explanation. I might post one more installment that shows the web app we made to create and maintain these JavaScript snippets.

Hope you’ve found this helpful!

Leave a Reply

Your email address will not be published. Required fields are marked *

 characters available