Services

Roughly speaking, a service is a piece of code (Java, Simple-method, Groovy, etc.) that can be run inside of the SCIPIO framework. SCIPIO services can also be “exported” as web services (SOAP, REST, XML-RPC, etc.) using the export=”true” option (attribute of the service element in it’s definition). Services can be chained (i.e. call each others), triggered by ECAs (Event Condition Action) and run asynchronously which gives them a lot of power and allow’s them to be implemented instantly. They always carry the session data in a context variable and can be rolled back if they threw an error (services are transactional with timeout).

Dissecting a Service

A service is composed of 3 parts:

  1. A declaration
  2. A definition
  3. An implementation

Declaration

Before a service can be used, you need to load it through a declaration file, which will contain your service definition. This is done inside your component configuration file.

<!-- Service definitions -->
<service-resource type="model" loader="main" location="servicedef/services.xml"/>

Definition

Services are defined in Service Definition Files, which are essentially XML files that describe the behavior of the service on a meta level. Service definitions consist of a unique name, a specific service engine (read: programming language) and location of the source (either the class or file location, i.e.: component://demosuite/script/com/ilscipio/data/OrderData.groovy). Input and output-fields are defined. Below is an example of a service definition:

<service name="userLogin" engine="java" location="org.ofbiz.commonapp.security.login.LoginServices" invoke="userLogin">
    <description>Authenticate a username/password; create a UserLogin object</description>
    <attribute name="login.username" type="String" mode="IN"/>
    <attribute name="login.password" type="String" mode="IN"/>
    <attribute name="userLogin" type="org.ofbiz.entity.GenericValue" mode="OUT" optional="true"/>
</service>

 

For a service definition, the following attributes are available:

Attribute Description
auth Does this service require authorization? (true/false)
debug Enable verbose debugging when calling this service?
default-entity-name The default Entity to use for auto-attributes
engine The name of the engine (defined in serviceengine.xml).
export Is this service allowed to be accessed via SOAP/HTTP/JMS? (true/false)
invoke The method name of the service.
location The location or package of the service’s class.
max-retry Sets the max number of times this service will retry when failed (persisted async only)
name The unique name of the service.
require-new-transaction Require a new transaction for this service
semaphore Defines how concurrent calls to this service should be handled:
none: multiple calls to this service may run concurrently
wait: while this service is running, queue any subsequent calls
fail: while this service is running, fail any subsequent calls
semaphore-wait-seconds When semaphore=”wait” how many seconds to wait before failing the service call
sempahore-sleep When semaphore=”wait” how often (in milliseconds) to check if the waiting service call can be run
transaction-timeout Override the default transaction timeout, only works if we start the transaction
use-transaction Create a transaction for this service (if one is not already in place)
validate Do we validate the attributes found below for name and type matching? (true/false)

The engine element defines the way the service will be implemented. Most commonly, this will be either java or groovy, but others, such as interface, entity-auto and group are available.

The system also supports Minilang, an xml based programming engine (referred to as “simple” in the engine definition), which is customary to the OFBiz community. Though there are many examples remaining throughout the system, SCIPIO is slowly replacing Minilang by other forms of implementation. Though still supported, Minilang has the tendency to generate slow-performing and often cluttered code fragments, we therefore recommend to rely on either Java or Groovy for service implementations.

Implementation

A typical service implementation accepts the DispatchContext (a Map that contains information about the current service context) and a service context (Map containing the IN-parameters). A result map is expected that contains the status of the service and all required OUT- & INOUT- parameters. Example:

public static Map<String, Object> serviceName(DispatchContext ctx, Map<String, ? extends Object> context) {
Map result = ServiceUtil.returnSuccess(); // creates empty Map with parameter "result" set to SUCCESS
// my Code ..

return resultMap;
}

Inside of the service you can rely on:

  • The delegator to access your entities (database)
    Delegator delegator = ctx.getDelegator();
    
  • The dispatcher for running services
    LocalDispatcher dispatcher = ctx.getDispatcher();

 

 

Literature