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:
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 usecase CreateInvoice(out Invoice invoice) { |
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; public class Order extends APPDUCXSAMPLE.generated.APPDUCXSAMPLE_200_300. @DUCXImplementation("APPDUCXSAMPLE@200.200:CreateInvoice") |
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.
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:
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, // Import for making available object class APPDUCXSAMPLE@200.200:Invoice // Import for making available class CreateInvoiceResult for retrieving // Import for making available the enumeration type APPDUCXSAMPLE@200.200: // Import for making available the compound type APPDUCXSAMPLE@200.200: |
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.
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 |
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.
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") // Initialize order date with current date and set order status to // Set express delivery for wholesalers // Add the order to the customer's list of orders |
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) { Java Implementation @DUCXImplementation("APPDUCXSAMPLE@200.200:AddPositionToOrder") // Create a new order position // Add the new order position to the order |
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) { Java Implementation @DUCXImplementation("APPDUCXSAMPLE@200.200:GetCustomerOrders") // The sort order is determined by a list of property definitions // Sort the customer's list of orders (the sorted list is returned in // Return the sorted list of orders |
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.
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") // Create a new instance of object class APPDUCXSAMPLE@200.200:Invoice // Reference the new invoice object in the order object and set |
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") // Check whether APPDUCXSAMPLE@200.200:DocumentCategoryOrder was selected |
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. |
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") // Invoke an XML web service to archive the order |
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") // Retrieve the existing order positions // Create a new entry and add it to the list of existing order positions // Write the modified list of order positions back to the order |
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") // Store the description string in a content // Create a structure of compound type COOSYSTEM@1.1:Content and // Invoke an XML web service to transmit the content |
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, inx, 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") // Create and populate global scope dictionary // Evaluate validation expression and get result if (result[0].getBool().getValue()) { |
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:
|
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") // Trace the number of pending orders // Load all properties of the pending order objects processPendingOrders(orders); |
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 COOCF_KEEPONFAILURE COOCF_KEEPREFRESHINFO COOCF_KEEPSEARCHINFO COOCF_KEEPVARIABLES COOCF_KEEPLOCKS COOCF_KEEPOBJECTS COOCF_NOTELESS |
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 COOTXF_NOREFRESH COOTXF_NOAUTOVERSION |
SetTransactionFlags(flags) | |
Backup() | |
Restore(data) | |
OpenScope() | |
CloseScope() | |
GetMaster() |
Table 32: Methods of the CooTransaction class
Example |
@DUCXImplementation("COOSYSTEM@1.1:ObjectPrepareCommit") |
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") try { |
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") // Determine if batch mode is enabled by checking transaction if (order != null && !batchmode) { |
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") // Set transaction variables TV_PRINTINVOICE and TV_INVOICE of @DUCXImplementation("APPDUCXSAMPLE@200.200:ShipOrder") if (printinvoice) { shipOrder(this); @DUCXImplementation("APPDUCXSAMPLE@200.200:SendInvoice") // Create and populate global scope dictionary // Make available the values stored in the global scope dictionary // Evaluate the invoice report template to get the HTML mail body mailbodycontent = reportresult.resultcontent; if (mailbodycontent != null) { |
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") // Get the pending orders of the current user // Trace the list of pending orders // Load all properties of the pending order objects processPendingOrders(orders); |
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.
The type of a customization point is accessible with the class TypeCustomizationPointDef.
Example |
public List<ActionParameterList> GetNameBuildInParameters() throws CooException { |
The customizations in a customization point can only be accessed through a use case implementation with Fabasoft Expression.