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.

text
<!-- 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:

Annotation

java
@Service(
    name = "userLogin",
    engine = "java",
    location = "org.ofbiz.commonapp.security.login.LoginServices",
    invoke = "userLogin",
    description = "Authenticate a username/password; create a UserLogin object",
    attributes = {
        @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")
    }
)
public interface UserLogin {}

XML

text
<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:

AttributeDescription
authDoes this service require authorization? (true/false)
debugEnable verbose debugging when calling this service?
default-entity-nameThe default Entity to use for auto-attributes
engineThe name of the engine (defined in serviceengine.xml).
exportIs this service allowed to be accessed via SOAP/HTTP/JMS? (true/false)
invokeThe method name of the service.
locationThe location or package of the service’s class.
max-retrySets the max number of times this service will retry when failed (persisted async only)
nameThe unique name of the service.
require-new-transactionRequire a new transaction for this service
semaphoreDefines 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-secondsWhen semaphore=”wait” how many seconds to wait before failing the service call
sempahore-sleepWhen semaphore=”wait” how often (in milliseconds) to check if the waiting service call can be run
transaction-timeoutOverride the default transaction timeout, only works if we start the transaction
use-transactionCreate a transaction for this service (if one is not already in place)
validateDo 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:

text
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)

    text
    Delegator delegator = ctx.getDelegator();
  • The dispatcher for running services

    text
    LocalDispatcher dispatcher = ctx.getDispatcher();

Literature#

Ask the people who wrote it.

Support, development and training from the team that builds Scipio ERP.