Script Action

The <action-script>, introduced in v5, can be used to create complex actions using scripting languages.

<action-script
  name="create.invoice" (1)
  model="com.axelor.sale.db.Order" (2)
  >
  <script
    language="js" (3)
    transactional="true" (4)
    >
  <![CDATA[
  var req = $request; (5)
  var res = $response; (6)
  var so = req.context;
  var invoice = new Invoice();
  invoice.date = so.confirmDate;
  // prepare invoice lines from sale order
  //TODO: invoice.invoiceLines = listOf(...);

  // if you want to save invoice
  //invoice.saleOrder = em.find(Order.class, so.id);
  //return $em.persist(invoice);

  res.setValue('invoice', invoice);
  res.setReadonly('customer', true);
  // and so on...
  ]]>
  </script>
</action-script>
1 the name of the action (required)
2 the name of the context model
3 scripting language to use (required, currently js and groovy only)
4 whether the code is transactional
5 the ActionRequest is available as $request
6 the ActionResponse is available as $response

The action-script is nothing but the controller method dynamically created using a scripting language. The $request and $response variables are nothing but the ActionRequest and ActionResponse parameters of controller method.

Following variables are available in script execution context:

Name Description

$request

the ActionRequest

$response

the ActionResponse

$em

the EntityManager if script is transactional

$json

instance of MetaJsonRecordRepository to work with custom models

The action-script can be used for custom models too. Here is an example:

<action-script name="create.hello" model="com.axelor.meta.db.MetaJsonRecord">
  <script language="js" transactional="true">
  <![CDATA[
    var hello = $json.create('hello'); (1)
    hello.name = "Hello!!!";           (2)

    var world = $json.all('world').by('name', '=', 'World!!!').fetchOne(); (3)
    if (world == null) {
        world = $json.create('world');
        world.name = "World!!!";
        world = $json.save(world); (4)
        // now we can't update world, as it's converted to real instance
    }

    hello.world = world;  (5)

    // return as response values
    $response.values = hello;

  ]]>
  </script>
</action-script>
1 create a new empty context for MetaJsonRecord for the hello model
2 the context allows seamless access to custom field values
3 find a world model record by field name
4 record(s) intended for relational field values must be saved manually
5 set relational value (m2o)

Using Java types

In js scripts, a bare capitalized name resolves directly to a Java type — entity and repository classes (by simple name, no import or FQN), plus the common java.time, java.math and java.util helpers (LocalDate, LocalDateTime, ZonedDateTime, Instant, BigDecimal, HashMap, ArrayList, Arrays, …​). Static members and constructors are usable directly:

var today = LocalDate.now();           // static method
var amount = new BigDecimal('1.50');   // constructor
var order = new Order();               // entity constructor
var repo = __repo__(Order);            // usable as a Class argument
var isOrder = record instanceof Order; // instanceof

For any other class, resolve it explicitly with Java.type():

var UUID = Java.type('java.util.UUID');
var id = UUID.randomUUID().toString();

All type access — bare names as well as Java.type() — is governed by the scripting policy. Depending on the configured policy a given class may or may not be accessible; a denied class fails at resolution, so don’t assume an arbitrary type is reachable.

A resolved type exposes the class’s static members and its constructor, not the instance methods of java.lang.Class. To reach the java.lang.Class object — for reflection, or getName() / getSimpleName() — go through .class (e.g. Order.class.getName()), and use the instanceof operator rather than Class.isInstance(…​). This applies to the js engine; in groovy, a bare name is the java.lang.Class object and statics, constructors and Class methods all work on it.

See available helper functions in script helper functions documentation.