2017 June Release

Implementing a use case in JavaPermanent link for this heading

Before you can start to implement use cases in Java, you have to enable Java support for your Fabasoft app.ducx project. You can enable Java support by selecting Enable Java support when creating a new Fabasoft app.ducx project. Java support may also be enabled later in the “Properties” dialog box of your Fabasoft app.ducx project (see next figure).

Figure 17: Enabling Java support for a Fabasoft app.ducx project

When enabling Java support, you have to provide a Package name and a Class folder for the classes generated automatically by Fabasoft app.ducx to allow you to access the Fabasoft Folio object model in Java. These classes are encapsulated in a Java package and put in a class folder, which is then added to your Fabasoft app.ducx project. The files generated by Fabasoft app.ducx are updated automatically whenever you modify your object model or your use case definitions.

It is possible to generate Java classes only for software components that are defined as shortcuts. Shortcuts for COOSYSTEM@1.1 and the own software component are mandatory and created automatically if not already defined. This way the compiling performance can be improved.

Strip unused symbols from output should be used for a release build to reduce the size of the JAR file. No stripping of unused symbols is an advantage in the development process because the project compiles faster.

Note:

  • JAR files of other software components in the Fabasoft Folio Domain are fetched when executing "Update All References". These JAR files can be referenced within the Fabasoft app.ducx project (“Properties” > “Java Build Path” > “Libraries” > “Add JARs”). The JAR files are located in the .references\lib folder. In a newly created project it may be necessary to refresh the project to be able to select the JAR files.
    Because the JAR files of the Fabasoft Folio Domain are used, no upload of these files is needed.
  • In the following examples, the package name APPDUCXSAMPLE.generated is used for the class files generated by Fabasoft app.ducx.

Defining a use case to be implemented in JavaPermanent link for this heading

The app.ducx use case language must be used to define the use case. For further information on how to define a use case, please refer to chapter “Defining use cases”.

When specifying the name of the Java method containing the implementation of your use case, the following syntax has to be used:

Syntax

impl = java:package.class.method;


After the java: prefix, specify the package name for your Java implementation package followed by the reference of the object class, and the name of the method. The individual parts must be separated by periods.

Example

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  usecase CreateInvoice(out Invoice invoice) {
    variant Order {
      java = APPDUCXSAMPLE.Order.CreateInvoice;
    }
  }
}

Implementing the Java methodPermanent link for this heading

When defining a use case implemented as a Java method, Fabasoft app.ducx will offer to generate a Java class and a method stub for your use case in the Java class on behalf of you.

After providing the name of the java method in the use case file, an error symbol is shown on the left-hand side next to the corresponding line in the source code indicating that the Java method does not exist yet. A Left-click on the error symbol opens a Quick Fix (see next figure).

In the Fabasoft app.ducx wizard dialog box, double-click “Create method…” to let the Fabasoft app.ducx wizard create a Java method stub for your use case.

Java methods may also be defined manually without the help of the app.ducx wizard. However, please note that all Java methods invoked from a use case must be attributed in the following format:

@DUCXImplementation("<Fully Qualified Reference of the Use Case>")

Furthermore, you may add your own member variables and methods that are not invoked by a use case to the Java classes generated by the Fabasoft app.ducx wizard as well.

Figure 18: app.ducx wizard for creating a Java method stub

The following example illustrates the Java source code generated by the Fabasoft app.ducx wizard for a typical Java method stub.

Example

package APPDUCXSAMPLE;

import CooLib.CooObject;
import CooLib.CooException;
import static APPDUCXSAMPLE.generated.DUCX.coort;
import static APPDUCXSAMPLE.generated.DUCX.cootx;
import APPDUCXSAMPLE.generated.DUCXImplementation;
import APPDUCXSAMPLE.generated.APPDUCXSAMPLE_200_300.actions.CreateInvoiceResult;

public class Order extends APPDUCXSAMPLE.generated.APPDUCXSAMPLE_200_300.
  classes.Order {
  public Order(CooObject obj) {
    super(obj);
  }

  @DUCXImplementation("APPDUCXSAMPLE@200.200:CreateInvoice")
  public CreateInvoiceResult CreateInvoice() throws CooException {
    CreateInvoiceResult result = new CreateInvoiceResult();
    // TODO: Auto-generated implementation stub
    return result;
  }
}


For a comprehensive example demonstrating how to implement a use case in Java, please refer to chapter “Comprehensive Java example”.

Note: The examples in the remainder of this chapter are not self-contained in order to improve readability. Required import statements are omitted to keep the examples more concise.

Importing packages generated by Fabasoft app.ducxPermanent link for this heading

The classes generated by Fabasoft app.ducx allow you to access the Fabasoft Folio object model so you can retrieve and set property values, invoke other use cases, and access component objects such as object classes. These classes reside in a separate package. The name of this package must be specified along with the class folder when enabling Java support for your app.ducx project.

Fabasoft app.ducx generates a set of Java class files for all software components referenced in your Fabasoft app.ducx project. The generated Java class files are updated as you add or remove software component references.

For each software component referenced in your Fabasoft app.ducx project, a package is created and the reference of the software component is used as package name. In this package, a class with the same name as the package is provided which contains get methods for accessing all component objects that belong to the software component.

This package also contains four sub packages that allow you to access object classes, to invoke use cases, and to use enumeration types and compound types:

  • The classes package contains classes for accessing object classes.
  • The actions package contains classes for transporting the output parameters when invoking use cases.
  • The enums package contains classes for working with enumeration types.
  • The structs package contains classes for working with compound types.

In order to keep your source code concise, it is recommended to add import statements to the header of your source files to import the packages you need.

Example

// Import for accessing component objects belonging to APPDUCXSAMPLE@200.200,
// e.g. the object representing the software component

import APPDUCXSAMPLE.generated.APPDUCXSAMPLE_200_300.APPDUCXSAMPLE_200_300;

// Import for making available object class APPDUCXSAMPLE@200.200:Invoice
import APPDUCXSAMPLE.generated.APPDUCXSAMPLE_200_300.classes.Invoice;

// Import for making available class CreateInvoiceResult for retrieving
// the output parameters after invoking the use case
APPDUCXSAMPLE@200.200:
// CreateInvoice

import APPDUCXSAMPLE.generated.APPDUCXSAMPLE_200_300.actions.CreateInvoiceResult;

// Import for making available the enumeration type APPDUCXSAMPLE@200.200:
// InvoiceState

import APPDUCXSAMPLE.generated.APPDUCXSAMPLE_200_300_enums.InvoiceState;

// Import for making available the compound type APPDUCXSAMPLE@200.200:
// OrderPosition

import APPDUCXSAMPLE.generated.APPDUCXSAMPLE_200_300.structs.OrderPosition;


In addition to the imports of packages generated by Fabasoft app.ducx, you also need to import parts of the CooLib package which contains some required classes. The library containing the CooLib package is automatically added to your project.

Data types in JavaPermanent link for this heading

Table 27 contains the list of data types used for accessing the Fabasoft Folio object model in Java.

Fabasoft Folio Data Type

app.ducx Keyword

Java Class

COOSYSTEM@1.1:STRING

string

java.lang.String

COOSYSTEM@1.1:BOOLEAN

boolean

java.lang.Boolean

COOSYSTEM@1.1:INTEGER

integer, time, timespan

java.lang.Integer

COOSYSTEM@1.1:FLOAT

float

java.lang.Double

COOSYSTEM@1.1:DATETIME

date, datetime

java.util.Date

COOSYSTEM@1.1:Currency

currency

COOSYSTEM_1_1.structs.Currency

COOSYSTEM@1.1:CONTENT

content

CooLib.CooContent

COOSYSTEM@1.1:DICTIONARY

dictionary

CooLib.CooDictionary

COOSYSTEM@1.1:OBJECT

object

CooLib.CooObject

Table 27: Data types in Java

Typed lists are used for accessing lists of values, i.e. properties allowing multiple values. For instance, the List<String> interface can be used for accessing a string list property of data type COOSYSTEM@1.1:STRINGLIST.

The type definition component objects for simple data types are accessible over the app.ducx class. For example, DUCX.getTypeBoolean() returns the type definition component object COOSYSTEM@1.1:BOOLEAN.

Accessing properties and invoking use casesPermanent link for this heading

The Fabasoft app.ducx wizard automatically generates methods for accessing properties and use cases belonging to the software components referenced in your Fabasoft app.ducx project. The generated methods allow you to retrieve and set property values and to invoke use cases.

Note: The object the use case is invoked on can be accessed using the this variable.

Please refer to chapter “Working with use case parameters” for detailed information on how to handle input and output parameters when implementing or invoking use cases.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:InitializeOrder")
public void InitializeOrder(final Person customer) throws CooException {
  // Lock the order object
  this.COOSYSTEM_1_1_ObjectLock(true, true, null, null);

  // Initialize order date with current date and set order status to
  // OS_PENDING

  this.APPDUCXSAMPLE_200_300_orderdate = new Date();
  this.APPDUCXSAMPLE_200_300_orderstate = OrderState.OS_PENDING;

  // Set express delivery for wholesalers
  if (customer.APPDUCXSAMPLE_200_300_customertype == CustomerType.
    CT_WHOLESALER) {
    this.APPDUCXSAMPLE_200_300_orderdelivery = DeliveryType.DT_EXPRESS;
  }
  else {
    this.APPDUCXSAMPLE_200_300_orderdelivery = DeliveryType.DT_STANDARD;
  }

  // Add the order to the customer's list of orders
  this.COODESK_1_1_ShareObject(null, null, APPDUCXSAMPLE_200_300.
    getProperty_customerorders(), customer);
}

Working with use case parametersPermanent link for this heading

Retrieving input parametersPermanent link for this heading

When you add a method implementation to your Java project, a signature is generated automatically for the new Java method. This signature contains a parameter list that corresponds to the parameter list of your use case. The input parameters defined for the use case are passed in to your Java method as Java objects.

Example

app.ducx Use Case Language

usecase AddPositionToOrder(Product product, integer quantity) {
  variant Order {
    impl = java:APPDUCXSAMPLE.Order.AddPositionToOrder;
  }
}

Java Implementation

@DUCXImplementation("APPDUCXSAMPLE@200.200:AddPositionToOrder")
public void AddPositionToOrder(final Product product, final Long
  quantity) throws CooException {
  // Lock the order
  this.COOSYSTEM_1_1_ObjectLock(true, true, null, null);

  // Create a new order position
  OrderPosition position = OrderPosition.create();
  position.APPDUCXSAMPLE_200_300_product = product;
  position.APPDUCXSAMPLE_200_300_quantity = quantity;

  // Add the new order position to the order
  List<OrderPosition> positions = this.APPDUCXSAMPLE_200_300_orderpositions;
  positions.add(position);
  this.APPDUCXSAMPLE_200_300_orderpositions = positions;
}

Returning output parametersPermanent link for this heading

Java methods do not support output parameters. Instead, a so-called result object must be used to return output parameters. The corresponding Java class for creating a result object is automatically created by a wizard when adding a new use case implementation in Java if the use case has one or more output parameters. The name of the Java class for retrieving the output parameters corresponds to the reference of the use case to be invoked, suffixed by the string “Result”.

When invoking another use case from within your Java method, you can follow the same approach for retrieving its output parameters: the invoked use case returns a result object containing a member variable for each output parameter.

Example

app.ducx Use Case Language

usecase GetCustomerOrders(out Order[] orders) {
  variant Person {
    impl = java:APPDUCXSAMPLE.Person.GetCustomerOrders;
  }
}

Java Implementation

@DUCXImplementation("APPDUCXSAMPLE@200.200:GetCustomerOrders")
public GetCustomerOrdersResult GetCustomerOrders() throws CooException {
  // Output parameters must be passed back using the result object
  GetCustomerOrdersResult result = new GetCustomerOrdersResult();

  // The sort order is determined by a list of property definitions
  ArrayList<Object> sortorder = new ArrayList<Object>();
  sortorder.add(APPDUCXSAMPLE_200_300.getProperty_orderdate());

  // Sort the customer's list of orders (the sorted list is returned in
  // the valuelist member variable of the SortResult object)

  SortResult sortresult = this.COOATTREDIT_1_1_Sort(
    this.APPDUCXSAMPLE_200_300_customerorders, true, sortorder, null);

  // Return the sorted list of orders
  result.orders = sortresult.valuelist;
  return result;
}


The result object provides the two methods SetError(CooObject) and SetError(CooObject, String). When calling SetError the output parameters are saved and afterwards the error raises an exception.

Working with objectsPermanent link for this heading

Creating new objects in Fabasoft FolioPermanent link for this heading

For creating a new instance of an object class, you can invoke the create method of the Java class representing the object class.

In the following example, a new instance of object class APPDUCXSAMPLE@200.200:Invoice is created and referenced in the APPDUCXSAMPLE@200.200:orderinvoice property of an order.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:MarkOrderAsShipped")
public void MarkOrderAsShipped() throws CooException {
  // Lock the order object
  this.COOSYSTEM_1_1_ObjectLock(true, true, null, null);

  // Create a new instance of object class APPDUCXSAMPLE@200.200:Invoice
  Invoice invoice = Invoice.create();

  // Reference the new invoice object in the order object and set
  // the order's state to OS_SHIPPED

  this.APPDUCXSAMPLE_200_300_orderinvoice = invoice;
  this.APPDUCXSAMPLE_200_300_orderstate = OrderState.OS_SHIPPED;
}

Comparing objectsPermanent link for this heading

You can use the equals method of an object to determine if it is equivalent to a given object instance in Fabasoft Folio.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:ProcessPendingOrders")
public void AddOrderCategory(final Case case) throws CooException {
  ComponentDocumentCategory category = this.COOTC_1_1001_objcategory;
  List<Object> casecategories = case.COOTC_1_1001_allowedcategories;

  // Check whether APPDUCXSAMPLE@200.200:DocumentCategoryOrder was selected
  // for the order object

  if (category.equals(APPDUCXSAMPLE_200_300.getClass_DocumentCategoryOrder())) {
    if (!casecategories.contains(APPDUCXSAMPLE_200_300.
      getClass_DocumentCategoryOrder())) {
      ComponentDocumentCategory.from(APPDUCXSAMPLE_200_300.
        get_DocumentCategoryOrder()).COODESK_1_1_ShareObject(null, null,
        COOTC_1_1001.getProperty_allowedcategories(), case);
    }
    else {
      coort.SetError(APPDUCXSAMPLE_200_300.
      getErrorMessage_CategoryAlreadyAdded());
    }
  }
  else {
    coort.SetError(APPDUCXSAMPLE_200_300.
    getErrorMessage_UnexpectedOrderCategory());
  }
}

Important methods of an objectPermanent link for this heading

Table 28 summarizes the most important methods that can be invoked on instances of Fabasoft Folio objects.

Method

Description

isValid()

isValid determines whether the object is valid.

IsClass(class)

IsClass determines whether the object class it is invoked on is derived from or identical to class.

HasClass(class)

HasClass determines whether the object is an instance of or derived from class.

GetClass()

GetClass returns the object class of the object.

GetName()

GetName returns the Name (COOSYSTEM@1.1:objname) of the object. If the name of the object cannot be read (e.g. because the user does not have sufficient rights for reading the object name), a string explaining why the name of the object cannot be read is returned.

GetAddress()

GetAddress returns the Address (COOSYSTEM@1.1:objaddress) of the object.

GetReference()

GetReference returns the Reference (COOSYSTEM@1.1:reference) of a component object.

GetIdentification()

GetIdentification returns the full identification of the object, which is a combination of the Address (COOSYSTEM@1.1:objaddress) and a version timestamp.

GetVersNr()

GetVersNr returns the version number of the object. If no version exists, „0“ is returned.

GetVersDate()

GetVersDate returns the date and time of the version of the object. This method can only be used for versions of objects, otherwise an exception is thrown. Use GetVersNr to find out whether the object is a version object.

LoadAllAttributes(tx)

LoadAllAttributes loads the values of all properties into the Fabasoft Folio Kernel Cache.

LoadSpecificAttributes(tx, properties)

LoadSpecificAttributes loads the values of the properties specified in properties into the Fabasoft Folio Kernel Cache.

HasAttribute(tx, property)

HasAttribute checks whether the specified property is assigned to the object.

HasAttributeValue(tx, property)

HasAttributeValue checks whether the specified property is assigned to the object and whether it is assigned a value.

CheckAccess(tx, accesstype)

CheckAccess checks whether accessing the object with the specified access type is allowed.

CheckGetAccess(tx, property)

CheckGetAccess checks whether the specified property of the object may be read.

CheckSetAccess(tx, property)

CheckGetAccess checks whether the specified property of the object may be changed.

IsGhost()

IsGhost checks whether object is still alive.

Table 28: Object methods

Working with enumeration types, compound types, contents, and dictionariesPermanent link for this heading

Working with enumeration typesPermanent link for this heading

The app.ducx wizard automatically generates Java classes for each enumeration type. These classes allow you to access all enumeration items of a particular enumeration type.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:ArchiveOrder")
public void ArchiveOrder() throws CooException {
  if (this.APPDUCXSAMPLE_200_300_orderstate == OrderState.OS_COMPLETED) {
    // Lock the order object and set the order state to OS_ARCHIVED
    this.COOSYSTEM_1_1_ObjectLock(true, true, null, null);
    this.APPDUCXSAMPLE_200_300_orderstate = OrderState.OS_ARCHIVED;

    // Invoke an XML web service to archive the order
    archiveOrderXML();
  }
  else {
    // Raise an error if the order is not completed yet
    coort.SetError(APPDUCXSAMPLE_200_300.getErrorMessage_InvalidOrderState());
  }
}

Working with compound typesPermanent link for this heading

Data structures representing compound types are referred to as compound values. Compound values must be created before they can be used. The create method of the Java class representing the compound type must be invoked for creating a new compound value.

The following example demonstrates how to add a new item to a compound property.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:AddPositionToOrder")
public void AddPositionToOrder(final Product product,
  final Long quantity) throws CooException {
  // Lock the order object
  this.COOSYSTEM_1_1_ObjectLock(true, true, null, null);

  // Retrieve the existing order positions
  List<OrderPosition> positions = this.APPDUCXSAMPLE_200_300_orderpositions;

  // Create a new entry and add it to the list of existing order positions
  OrderPosition position = OrderPosition.create();
  position.APPDUCXSAMPLE_200_300_product = product;
  position.APPDUCXSAMPLE_200_300_quantity = quantity;
  positions.add(position);

  // Write the modified list of order positions back to the order
  this.APPDUCXSAMPLE_200_300_orderpositions = positions;
}

Working with contentsPermanent link for this heading

In Java, contents are represented by the CooContent class. The next table shows the most important methods supported by CooContent.

Method

Description

GetFile(name, generatetemp)

GetFile copies the CooContent to a file and returns the file name. name denotes the name of the file to be created.

SetFile(name, removeonrelease)

SetFile stores the content of a file in a CooContent. name denotes the name of the file to be used as a source.

GetContent(tx, flags, codepage)

GetContent returns a CooContent as a String and can only be used for retrieving text-based contents.

SetContent(tx, flags, codepage, string)

SetContent stores a String in a CooContent.

Table 29: Methods of the CooContent class

In the following example, a string property of type COOSYSTEM@1.1:STRINGLIST is retrieved as a scalar string and stored in a CooContent. Please note that the CooContent has to be initialized first by invoking the CreateContent method of the Fabasoft Folio Runtime. Afterwards, the CooContent is stored in a compound value of type COOSYSTEM@1.1:Content.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:SendProductDescription")
public void SendProductDescription() throws CooException {
  // Get the product description as a scalar string value
  // Note: this.
APPDUCXSAMPLE_200_300_productdescription returns a List<String>
  String description = this.GetAttributeString(cootx, APPDUCXSAMPLE_200_300.
    getProperty_productdescription(), null, CooFlags.COODISP_ROWLIST);

  // Store the description string in a content
  CooContent descriptioncontent = coort.CreateContent();
  descriptioncontent.SetContent(cootx, CooFlags.COOGC_MULTIBYTEFILE,
    CooFlags.COOGC_UTF8, description);

  // Create a structure of compound type COOSYSTEM@1.1:Content and
  // store the content in this structure

  Content content = Content.create();
  content.COOSYSTEM_1_1_contcontent = descriptioncontent;
  content.COOSYSTEM_1_1_contextension = "txt";

  // Invoke an XML web service to transmit the content
  sendProductDescriptionXML(content);
}

Working with dictionariesPermanent link for this heading

In Java, dictionaries are represented by the CooDictionary class, which allows you to store a list of key-value pairs. The key must be a String value. The next table lists the most important methods supported by the CooDictionary class.

Method

Description

GetEntry(key)

GetEntry returns the list of values stored under key. Use this method for retrieving lists from a dictionary.

GetEntryValue(key)

GetEntryValue returns value stored under key. Use this method for retrieving scalar values from a dictionary.

GetEntryValueCount(key)

GetEntryValueCount returns the number of values of the entry specified by key.

GetEntryCount()

GetEntryCount returns the number of entries in a dictionary.

GetEntryKey(index)

GetEntryKey returns the key of the entry of the specified index.

SetEntry(key, values)

SetEntry creates an entry under key for the specified values. Use this method for storing lists of values in a dictionary.

SetEntryValue(key, value)

SetEntryValue creates an entry under key for the specified value. Use this method for storing a scalar value in a dictionary.

TestEntry(key)

TestEntry checks whether a dictionary contains an entry under key. This method returns true if the value stored under key is null.

HasEntry(key)

HasEntry checks whether a dictionary contains an entry under key. This method returns false if the value stored under key is null.

ClearEntry(key)

ClearEntry removes the entry stored under key from a dictionary.

Reset()

Reset removes all entries from a dictionary.

Backup()

Backup serializes the contents of a dictionary to a string.

Restore(string)

Restore rebuilds a dictionary from a serialized string.

Table 30: Methods of the CooDictionary class

In many cases, dictionaries are used as local or global scope when evaluating app.ducx expressions.

Note: Before you can use a CooDictionary, it has to be initialized by invoking the CreateDictionary method of the Fabasoft Folio Runtime.

In the following example, an expression is evaluated by the implementation of use case APPDUCXSAMPLE@200.200:ValidateInvoice. The invoice object is provided in the local scope, and a dictionary is provided in the global scope.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:ValidateInvoice")
public void ValidateInvoice() throws CooException {
  Invoice invoice = this;
  Date paymentdate = invoice.APPDUCXSAMPLE_200_300_invoicepaymentdate;
  InvoiceState invoicestate = invoice.APPDUCXSAMPLE_200_300_invoicestate;

  String expressiontext = getValidationExpression(invoice);

  // Create and populate global scope dictionary
  CooDictionary globalscope = coort.CreateDictionary();
  globalscope.SetEntryValue("paydate", paymentdate);
  globalscope.SetEntryValue("state", invoicestate);

  // Evaluate validation expression and get result
  CooValue[] result = CooExpression.Evaluate(cootx, expressiontext,
    CooValue.asArray(globalscope), CooValue.asArray(invoice));

  if (result[0].getBool().getValue()) {
    // Validation expression returned "true"
    processInvoice(invoice);
  }
  else {
    // Validation expression returned "false"
    coort.SetError(APPDUCXSAMPLE_200_300.getErrorMessage_ValidationError());
  }
}

Accessing the Fabasoft Folio RuntimePermanent link for this heading

When implementing a method in Java, the static variable coort of the DUCX package can be used to access the Fabasoft Folio Runtime. The next table contains a list of the most important methods supported by the Fabasoft Folio Runtime.

Method

Description

CreateContent()

CreateContent initializes a new CooContent object. Please note that this is a memory structure, and not a persistent object in Fabasoft Folio.

CreateDictionary()

CreateDictionary initializes a new CooDictionary object. Please note that this is a memory structure, and not a persistent object in Fabasoft Folio.

GetCurrentUser()

GetCurrentUser returns the user object of the user currently logged in to Fabasoft Folio.

GetCurrentUserEnvironment()

GetCurrentUserEnvironment returns the active user environment object of the user currently logged in to Fabasoft Folio.

GetCurrentUserRoot()

GetCurrentUserRoot returns the desk object of the user currently logged in to Fabasoft Folio.

GetCurrentUserLanguage()

GetCurrentUserLanguage returns the language of the user currently logged in to Fabasoft Folio.

GetCurrentUserRoleGroup()

GetCurrentUserRoleGroup returns the group object of the current role of the user currently logged in to Fabasoft Folio.

GetCurrentUserRolePosition()

GetCurrentUserRolePosition returns the position object of the current role of the user currently logged in to Fabasoft Folio.

GetObject(address)

GetObject returns the object with the specified address.

SearchObjects(tx, query)

SearchObjects executes a Fabasoft Folio query and returns the matching objects.

SetError(errormessage)

SetError returns a CooException using the errormessage object.

LoadAllAttributes(tx, objects)

LoadAllAttributes loads the values of all properties of the specified objects into the Fabasoft Folio Kernel Cache.

Log(string)

Log writes the specified string to Fabasoft app.telemetry.

Log(level, string)

Log writes the specified string to Fabasoft app.telemetry using the specified level.

level can be one of the following values:

  • COOLL_LOG
  • COOLL_IPC
  • COOLL_NORMAL
  • COOLL_DETAIL
  • COOLL_DEBUG
  • COOLL_DEFAULT (same as COOLL_DETAIL)

Trace(string)

Trace writes the specified string to the Fabasoft app.ducx Tracer (also if the software component is not in trace mode).

Trace(string, value)

Trace writes the specified string and a value of arbitrary data type to the Fabasoft app.ducx Tracer (also if the software component is not in trace mode).

ReportEvent(source, string, type, category)

ReportEvent creates a new entry in the event log.

Table 31: Methods of the Fabasoft Folio Runtime

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:ProcessPendingOrders")
public void ProcessPendingOrders() throws CooException {

  // Get the pending orders of the current user
  User user = (User) coort.GetCurrentUser();
  List<Order> pendinglist = user.APPDUCXSAMPLE_200_300_pendingorders;

  // Trace the number of pending orders
  coort.Trace("Found " + pendinglist.size() + " pending orders");

  // Load all properties of the pending order objects
  Order[] orders = pendingList.toArray(new Order[pendinglist.size()]);
  coort.LoadAllAttributes(cootx, orders);

  processPendingOrders(orders);
}

Accessing the transaction contextPermanent link for this heading

When implementing a method in Java, the static variable cootx of the DUCX package can be used to access the current transaction context. cootx returns an instance of Java class CooTransaction. The most important methods of the CooTransaction class are listed in the next table.

Method

Description

Abort()

Abort aborts the current transaction and rolls back any changes.

Commit()

Commit closes the current transaction and stores any changes.

CommitEx(flags)

CommitEx closes the current transaction and stores any changes.

Additionally, the following flags are supported:

COOCF_NORMAL
Normal commit

COOCF_KEEPONFAILURE
If commit fails, all transaction data is kept

COOCF_KEEPREFRESHINFO
After commit the refresh info of all touched object is kept

COOCF_KEEPSEARCHINFO
After commit the search info of the searches executed in this transaction is kept

COOCF_KEEPVARIABLES
After commit all transaction variables are kept

COOCF_KEEPLOCKS
After commit all locks of objects are kept

COOCF_KEEPOBJECTS
After commit all modified objects are stored in the transaction variable COOSYSTEM@1.1:TV_COMMITTEDOBJECTS

COOCF_NOTELESS
If specified the properties COOSYSTEM@1.1:objmodifiedat and COOSYSTEM@1.1:objchangedby are not set. This flag is only allowed, if the current user has the role COOSYSTEM@1.1:SysAdm and the current user is registered in COOSYSTEM@1.1:domainmasterusers of the current domain object

Persist(object)

Persist temporarily stores the state of the current transaction without committing the changes.

Clone()

Clone returns a clone of the current transaction.

HasVariable(swc, id)

HasVariable checks whether transaction variable id of software component swc contains a value. This method returns false if if the value stored is null.

TestVariable(swc, id)

TestVariable checks whether transaction variable id of software component swc contains a value. This method returns true even if the value stored is null.

ClearVariable(swc, id)

ClearVariable removes transaction variable id of software component swc from the transaction.

GetVariable(swc, id)

GetVariable retrieves the list of values stored in transaction variable id of software component swc.

SetVariable(swc, id, type, values)

SetVariable stores the specified values in transaction variable id of software component swc.

GetVariableValueCount(swc, id)

GetVariableValueCount returns the number of values stored in transaction variable id of software component swc.

HasVariableValue(swc, id)

HasVariableValue returns true if a transaction variable id of software component swc is available.

GetVariableValue(swc, id)

GetVariableValue retrieves a scalar value stored in transaction variable id of software component swc.

SetVariableValue(swc, id, type, value)

SetVariableValue stores the specified scalar value in transaction variable id of software component swc.

GetVariableString

GetVariableStringEx

GetVariableTypeDefinition(swc, id)

GetVariableTypeDefinition returns the type definition for the variable stored in transaction variable id of software component swc.

IsClone()

IsModified()

IsModified checks whether objects were modified within the transaction.

IsModifiedEx()

IsModifiedEx checks whether any data was modified within the transaction.

IsCreated(object)

IsCreated checks whether object was created in this transaction.

IsDeleted(object)

IsDeleted checks whether object was deleted in this transaction.

IsChanged(object)

IsChanged checks whether object was changed in this transaction.

IsAttributeChanged(object, property)

IsAttributeChanged checks whether property of object was changed in this transaction.

GetTransactionFlags()

GetTransactionFlags retrieves the flags of the transaction:

COOTXF_ROLECHANGED
During the transaction an automatic role change has been performed

COOTXF_NOREFRESH
Objects are not automatically refreshed when accessed with this transaction

COOTXF_NOAUTOVERSION
During commit of the transaction no automatic version will be created

SetTransactionFlags(flags)

Backup()

Restore(data)

OpenScope()

CloseScope()

GetMaster()

Table 32: Methods of the CooTransaction class

Example

@DUCXImplementation("COOSYSTEM@1.1:ObjectPrepareCommit")
public void InvoicePrepareCommit(final Boolean internalchange)
  throws CooException {
  // Check if the invoice has been created in the current transaction
  // and if property
APPDUCXSAMPLE@200.200:invoicestate has been changed
  if (!cootx.IsCreated(this) && cootx.IsAttributeChanged(this,
   APPDUCXSAMPLE_200_300.getProperty_invoicestate())) {
    // Rebuild the object's name based on the name build configuration
    this.FSCCONFIG_1_1001_ObjectPrepareCommitNameBuild();
  }
}

Creating a new transactionPermanent link for this heading

In some scenarios it is necessary to carry out operations in a separate transaction. Any changes that have been made in a new transaction can be committed or rolled back separately from the main transaction.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:CreateInvoice")
public void CreateInvoice() throws CooException {
  // Create a new transaction
  CooTransaction backuptx = DUCX.cootx;
  CooTransaction localtx = new CooTransaction();

  try {
    // Perform the following operations in context of the new transaction
    coort.SetThreadTransaction(localtx);

    Invoice invoice = Invoice.create();
    this.APPDUCXSAMPLE_200_300_InitializeInvoice(invoice);

    // Commit the changes
    localtx.Commit();
  }
  catch (Exception ex) {
    // In case of an error, roll back the changes
    localtx.Abort();
  }
  finally {
    // Restore original transaction context
    coort.SetThreadTransaction(backuptx);

    // Clear the variables holding the transactions
    backuptx = null;
    localtx = null;
  }
}

Working with transaction variablesPermanent link for this heading

A transaction variable is a temporary variable identified by a software component, a transaction variable reference, and a unique identification number. Transaction variables must be declared using the app.ducx use case language before they can be used. For further information on how to declare transaction variables, please refer to chapter “Declaring transaction variables”.

For accessing a transaction variable, you need a combination of either software component reference and transaction variable reference or software component reference and transaction variable identification number.

Transaction variables are stored and transported in the so called transaction context, i.e. they are cleared when a transaction is committed or aborted.

The purpose of transaction variables is to transfer status information between different use cases invoked within the same transaction.

In some cases, necessary context information cannot be provided in form of parameters when a use case is invoked. For example, the Fabasoft Folio workflow engine makes available a set of four transaction variables (see next table) when a work item of an activity is executed by a user.

Identifier

Description

WFVAR_THIS

Transaction variable WFVAR_THIS of COOWF@1.1 holds the business object attached to the process.

WFVAR_PROCESS

Transaction variable WFVAR_PROCESS of COOWF@1.1 holds the process instance.

WFVAR_ACTIVITY

Transaction variable WFVAR_ACTIVITY of COOWF@1.1 holds the current activity instance.

WFVAR_WORKITEM

Transaction variable WFVAR_WORKITEM of COOWF@1.1 holds the zero-based index of the work item executed by the user.

Table 33: Transaction variables provided by COOWF@1.1 when executing a work item

To access transaction variables, you need to use the access methods exposed by the cootx interface object of the DUCX package (see chapter “Accessing the transaction context”).

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:ReleaseOrder")
public void ReleaseOrder() throws CooException {
  // Get the order object from transaction variable 1 of COOWF@1.1
  Order order = Order.from(cootx.GetVariableValue(COOWF_1_1.
    getSoftwareComponent(), 1).getObject());

  // Determine if batch mode is enabled by checking transaction
  // variable TV_BATCHMODE of COOSYSTEM@1.1

  Boolean batchmode = COOSYSTEM_1_1.getTransactionVariables_TV().
    COOSYSTEM_1_1_TV_BATCHMODE;

  if (order != null && !batchmode) {
    releaseOrder(order);
  }
}


For your software component, you may also declare your set of transaction variables using the app.ducx use case language and use them in your Java code as illustrated by the following example.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:ProcessOrder")
public void ProcessOrder() throws CooException {
  if (processOrder(this)) {
    Invoice invoice = this.APPDUCXSAMPLE_200_300_orderinvoice;
    Boolean printinvoice = invoice.APPDUCXSAMPLE_200_300_invoicestate ==
      InvoiceState.IS_PENDING;

    // Set transaction variables TV_PRINTINVOICE and TV_INVOICE of
    //
APPDUCXSAMPLE@200.200
    COOSYSTEM_1_1.getTransactionVariables_TV().
     APPDUCXSAMPLE_200_300_TV_PRINTINVOICE = printinvoice;
    COOSYSTEM_1_1.getTransactionVariables_TV().
     APPDUCXSAMPLE_200_300_TV_INVOICE = invoice;
  }
}

@DUCXImplementation("APPDUCXSAMPLE@200.200:ShipOrder")
public void ShipOrder() throws CooException {
  // Retrieve and evaluate transaction variable TV_PRINTINVOICE of
  //
APPDUCXSAMPLE@200.200
  Boolean printinvoice = COOSYSTEM_1_1.getTransactionVariables_TV().
   APPDUCXSAMPLE_200_300_TV_PRINTINVOICE

  if (printinvoice) {
    Invoice invoice = COOSYSTEM_1_1.getTransactionVariables_TV().
     APPDUCXSAMPLE_200_300_TV_INVOICE;
    invoice.APPDUCXSAMPLE_200_300_SendInvoice();
  }

  shipOrder(this);
}

@DUCXImplementation("APPDUCXSAMPLE@200.200:SendInvoice")
public void SendInvoice() throws CooException {
  Invoice invoice = this;
  Order order = invoice.APPDUCXSAMPLE_200_300_invoiceorder;
  ContactPerson customer = order.APPDUCXSAMPLE_200_300_ordercustomer;
  CooContent mailbodycontent = coort.CreateContent();

  // Create and populate global scope dictionary
  CooDictionary globalscope = coort.CreateDictionary();
  globalscope.SetEntryValue("invoice", invoice);
  globalscope.SetEntryValue("order", order);
  globalscope.SetEntryValue("customer", customer);

  // Make available the values stored in the global scope dictionary
  // when the invoice report is evaluated by initializing transaction

  // variable 1 of COOAR@1.1

  cootx.SetVariableValue(COOAR_1_1.getSoftwareComponent(), 1,
    DUCX.getTypeDictionary(), globalscope);

  // Evaluate the invoice report template to get the HTML mail body
  CreateReportResult reportresult = invoice.COOAR_1_1_CreateReport(
   APPDUCXSAMPLE_200_300.getClass_InvoiceTemplateReport(), false, null, null,
    mailbodycontent);

  mailbodycontent = reportresult.resultcontent;

  if (mailbodycontent != null) {
    Addressee mainaddress = customer.FSCFOLIO_1_1001_mainaddress;
    String recipient = mainaddress.FSCFOLIO_1_1001_emailaddress;
    String sender = "orderprocessing@APPDUCXSAMPLE.fabasoft.com";
    String subject = invoice.GetName();

    ArrayList<String> recipients = new ArrayList<String>();
    recipients.add(recipient);

    ArrayList<CooContent> mailbody = new ArrayList<CooContent>();
    mailbody.add(mailbodycontent);

    %%TRACE("Mail Recipient:", recipient);
    %%TRACE("Mail Subject:", subject);
    %%TRACE("Mail Body:", mailbodycontent.GetContent(cootx,
      CooFlags.COOGC_MULTIBYTEFILE, CooFlags.COOGC_UTF8));

    // Send the invoice mail to the customer
    invoice.FSCSMTP_1_1001_SendHTML(sender, recipients, subject, mailbody,
      null, null, null, null, null, null, null);
  }
}

Tracing in JavaPermanent link for this heading

In addition to using the tracing functionality built into Fabasoft app.ducx described in chapter “Tracing in Fabasoft app.ducx projects”, you may also write custom trace messages to Fabasoft app.ducx Tracer.

You can use the Trace method of the coort interface object for invoking the trace functionality of the Fabasoft Folio Runtime. However, this method only supports tracing simple strings.

The trace method of the DUCX class is more powerful, and allows you to trace all kinds of Fabasoft Folio data types.

Moreover, the DUCX class also exposes the traceEnter and traceLeave methods that can be used for logging in the trace output when your Java method has been entered and left.

Example

@DUCXImplementation("APPDUCXSAMPLE@200.200:ProcessPendingOrders")
public void ProcessPendingOrders() throws CooException {
  DUCX.traceEnter();

  // Get the pending orders of the current user
  User user = (User) coort.GetCurrentUser();
  List<Order> pendinglist = user.APPDUCXSAMPLE_200_300_pendingorders;

  // Trace the list of pending orders
  DUCX.trace("List of Orders:", pendinglist);

  // Load all properties of the pending order objects
  Order[] orders = pendingList.toArray(new Order[pendinglist.size()]);
  coort.LoadAllAttributes(cootx, orders);

  processPendingOrders(orders);

  DUCX.traceLeave();
}

Support of old style Java implementationPermanent link for this heading

If a Java archive (.jar) file with an old style java implementation is used, the Java support must not be activated in the app.ducx project.

For all defined Java implementation neither the package string is verified nor the prefix is generated For further information on how to attach a trigger action to a trigger event in a property definition, please refer to chapter “Defining a use case to be implemented in Java”.

If the project is loaded into a Fabasoft domain, the Java archive (.jar) file has to be copied manually to the web server.

Working with type definition of a customization pointPermanent link for this heading

The type of a customization point is accessible with the class TypeCustomizationPointDef.

Example

public List<ActionParameterList> GetNameBuildInParameters() throws CooException {
  //Get the type of the customization point
  TypeCustomizationPointDef cptdef = FSCCONFIG_1_1001.getCPT_NameBuild();
  //Return customization point parameters
  List<ActionParameterList> parameters = tcpt.COOSYSTEM_1_1_typecpparameters;
  ...

  return inparameters;
}

The customizations in a customization point can only be accessed through a use case implementation with Fabasoft Expression.