Fluent Groovy Services vs Groovy Services

   Journey PlatformPreviously known as the Transact Platform.  |   Platform Developer |  5.1 & Higher This feature is related to 5.1 and higher. |  Deprecated in 17.10 This feature was deprecated in 17.10.

Journey Manager is based on an extensible service-oriented architecture, which enables developer to implement highly configurable services written in GroovyGroovy is a powerful scripting language which runs on the Java Virtual Machine. Across theJourney platform, Groovy is used to create services in Manager. These services are primarily used to create plug-in style systems that interact with Manager. language. There are two types of service to choose from to implement a new Groovy service: Fluent Groovy service and Groovy service. The main difference between them is:

  • Fluent Groovy service uses Transact Fluent API.
  • Groovy service uses Transact Core API.
Note

It is strongly recommended to use the Fluent Groovy service for any new clients, services and applications development. If this can't be done due to limitations in the Fluent APIs, Groovy services must be used. However, some efforts must be made to migrate existing Groovy services to Fluent ones, whenever possible, because Manager future version will force everyone to only use the Fluent APIs.

The detailed difference between the services is outlined below.

Fluent Groovy Service

The Fluent Groovy service is a service that can only use Transact Fluent API. It is impossible to call any Transact Core API from this service. The reasons are as follows:

  • Simplify and speed up service implementation for developers because they need to know only limited set of Fluent APIs (34 Fluent API classes vs 1042 Core API classes)
  • Enable to use the Fluent programming model, see the example below:
  • 
    import com.avoka.tm.svc.*
    def params = [:] params.refNumber = ...
    def result = new GroovyServiceInvoker()
    .setServiceName("Ref Lookup")
    .setClientCode("maguire")
    .setVersion("0.2.1")
    .invoke(params)
    
  • Allows to use short names, and immutable value objects
  • Reduce time to market and reduce development costs
  • Faster to train developers and scale teams
  • More supportable and stable API contract, because they are better regression tested
  • Easier upgrades
  • Improved system performance
  • Better architecture for writing server-side business logic where services are tied to a single trigger point and can be used across a range of triggers and arbitrary invocations
  • Allows Groovy types checking
  • Restricted from using Transact Core APIs to prevent developers from running into implementation troubles or design confusions. For example, object mapping API is restricted, but value objects API is allowed.
  • Enforces the Java-like class syntax, as opposed to script-like syntax. It makes development more structured. In the above example, if you create a new service from Fluent Dynamic Data template, your new Groovy script will look like this (compare to the script example in the Groovy Service section):
  • 
    import com.avoka.tm.util.*
    import com.avoka.tm.vo.*
    import javax.servlet.http.*
     
    class FluentDynamicData {
    	public Logger logger
    	String invoke(SvcDef svcDef, Txn txn, HttpServletRequest request, User user) {
    		String data = '''{ "address": { "firstLine": "123 Wall Street" } }'''
    		return data
    	}
    }
    
Note

Developers are encouraged to create new services as Fluent Groovy services. Developers might encounter a few situations when it is difficult, if yet possible, to implement a service using Fluent Groovy service (due to Transact Fluent API limitations). However, it can be resolved on case by case basis. For more information, see Fluent Groovy Service Developer Guide.

Note

Fluent service can only invoke Dynamic Groovy services, if the install time Groovy Secure API restriction is not enforced.

Groovy Service

The Groovy Service uses both Transact Core API and Transact Fluent API, which allows developers to implement nearly any service possible. However, there are number of disadvantages that are listed below:

  • Implementation can become complex and labor extensive because there are hundreds of APIs to learn and use. This significantly increase the development cost.
  • Developers should have deep understanding of the APIs to be able to write services.
  • High possibility to execute potentially dangerous code that can crash the whole Manager server, for example System.exit(), or directly manipulate with database objects.
  • Groovy code is not stable because it relays of Transact Core API that can change and will change over time to accommodate for bug fixes and Manager new features.
  • There is no type checking or any other static checks on the Groovy service code, so often the first time you would find out something had broken was when it failed at runtime.
  • Provides the script-like syntax. In the above example, if you create a new service from Groovy Dynamic Data template, your new Groovy script will look like this:
  • 
    import com.avoka.core.groovy.GroovyLogger as logger
    def data = '''{
    	"address": {
    		"firstLine": "123 Wall Street"
    	}
    }'''
    return data
    
Note

Developers are discouraged to create new services using core Groovy services, which are considered the legacy API and have been deprecated since Journey Manager version 19.11. Instead, whenever possible, use Fluent Groovy Service .

As the core API are deprecated, you can find all legacy Groovy services, which use these core API, by running the following script in the Groovy console with the Secure Fluent API Only checkbox unselected.

import com.avoka.fc.core.dao.*
import com.avoka.tm.query.*
import com.avoka.tm.vo.*

List<SvcDef> svcDefs = new SvcDefQuery()
      .withCurrentVersion()
      .setFetchLimit(50000)
      .listValues()

println "all services: " + svcDefs.size()

def legacyServices = svcDefs.collect{ svcDef ->
    def svc = DaoFactory.serviceDefinitionDao.getServiceDefinitionForPK(svcDef.id)
    return !svc.isFluentApiService() ? svc : null
}.findAll {it && it.getClassnameBeanname().contains("Groovy") }

println "all non fluent services: " + legacyServices.size()

legacyServices.collect { it.serviceName + " >> " + it.serviceType }.each {
  println it
}

Configuration Example

To create a new Dynamic Data service (Groovy service) from Services menu, you have an option to create this service based on the Fluent Dynamic Data Template (Fluent Groovy service), or Groovy Dynamic Data Template (Groovy service), as shown below.

Note

It is recommended to use Fluent Groovy service.

Next, learn about Transact Fluent SDK.