A Jadex agent is synchronized in the sense, that only one plan step at a time is executed (or none, if the agent is busy performing internal reasoning processes). Sometimes you want to access agent internals from external threads. A good example is when your agent provides a graphical user interface (GUI) to accept user input. When the user clicks a button your Java AWT/Swing event handler method is called, which is executed on the Java AWT-Thread (there is one AWT Thread for each Java virtual machine instance). To force that such external threads are properly synchronized with the internal agent execution, you are not allowed to call Jadex methods directly from those threads. If you try to do so, a runtime exception “Wrong thread calling plan interface” will be thrown.
The AbstractPlan class provides a method getExternalAccess()
which returns an accessor which automatically does the necessary thread synchronization.
This accessor implements the ICapability
interface, providing access
to all features of the capability (beliefbase, goalbase, etc.). In addition, some convenience methods
are provided to wait for goals to be completed or messages to be received. These
methods should be used with caution, as they could easily lead to deadlocks.
To avoid at least one source of deadlocks, it is not possible to call methods on
this accessor from the plan thread. Whenever you call the wrong object from
the wrong thread, a RuntimeException will immediately identify the problem.
The following code presents an example where a belief is changed when the user
presses a button.
public void body() { ... JButton button = new JButton("Click Me"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // This code is executed on the AWT thread (not on the plan thread!) IBeliefbase bb = getExternalAccess().getBeliefbase(); bb.getBelief("button_pressed").setFact(new Boolean(true)); } }); ... }
Figure 16.1. External process example