Documentation

The documentation assumes some familiarity with Dipforge, such as how to access the development environment. If you are interested in this information first read the download documentation.

Note: Code references used in the below examples can be found in the test, desktop, or ide projects included with a Dipforge instance. All code in these projects can be edited freely.

Overview

This document covers development within the Dipforge. It covers the following areas:

Introduction

The development environment in Dipforge is availabe through the Web Based IDE. This IDE provides the ability to manage the projects, types, controls, views, flows, services, packages and times. This is the core of the Dipforge development environment.

Project Structure

The project system in Dipforge is designed to provide a way to neatly encapsulate your development. Be that web development, business process development, integration or scheduled processing. All of this is accessible through the IDE, and first thing that is present through it is a list of all available projects. The default list is as follows :

  • dipforge: A core project shared by all the others.
  • public: All frontends developed here are visible externally without authentication.
  • bss: (Business Support Systems) A telecommunications term for business systems.
  • oss: (Operational Support Systems) A telecommunications term for operational systems.
  • ide: The integrated development environment.
  • desktop: The desktop.
  • test: A test example.
  • tools: A directory to develop tools in.
Using the IDE it is possible to delete and create new projects at will except for the dipforge and public projects. Projects consists of distinct areas. Each area focuses on a particular level of functionality. These areas are :
  • config: The configuration for the project.
  • controls: The controllers for the frontend.
  • views: The presentation layer for the frontend.
  • flows: The business process or workflows, written in Leviathan Script.
  • services: The end points invoked by the workflow.
  • packages: Groovy classes implemented to contain common functionality needed by controls, views and services.
  • lib: Java library dependencies.

config

The configuration for a project, it contains the following files by default:
  • project_types.xml: The dynamic types that are defined by this project. They can be used by any other project but are defined and maintained within this project.
  • project_actions.xml: The actions associated with types and implemented by flows. An manipulation of a type requires the invocation of the appropriate event and flow.
  • project_methods.xml: The methods are backend services that can be invoked by the flows and can consume the types.
  • project_times.xml: Cron like configuration for scheduled processing.
When a new project is created these file will be parsed to contain the default configuration information. Example configuration will also so be supplied in a comment block.

control

Simple groovy script files that control the flows of the application and access to the model data defined by the dynamic types. Types are persisted as RDF data and the controllers can query this information in a read only way. Any updates to this information have to pass through the workflow engine in order to persist to the master rdf store of which the frontend is a slave.

views

Simple gsp pages or groovy server pages. Simpler to JSP in implementation but a lot easier to work with. The controllers can pass data to these pages as read only format thus preventing the views from attempting to directly update the data.

flows

The flows contain the definition of workflow defined in Leviathan Script. Leviathan Script is a domain specific language designed to make implementing ESB and Workflow logic easier. It does this by hiding all the complexity of asynchronous processing from the user and allowing them to focus purely on task at hand.

services

The folder containing the Groovy Script classes that manage the end points for the flows. Scripts can be implemented to integrate into external systems, make calls on Dipforge Java API’s, or manage the environment in which Dipforge runs. When invoked by a flow the data from said flow is passed in as parameters, no data transformation is required. This makes them very easy to implement and very rapid to develop.

packages

Common Groovy classes used by the services, controllers or views. This is the place to store and develop common functionality.

lib

Java Libraries used by the project.

Dynamic Types

Dipforge implements a powerful and flexible dynamic type system, using RDF ( Resource Description Framework). This is seen as a common data layer throughout Dipforge, something that is essential to any Enterprise System or to a BSS/OSS environment. Types can be rapidly defined and when published the schema generated is exposed to the rest of the environment via http. This makes it possible to share types between projects and systems by referencing the RDF Schema.

Dipforge further takes advantage of these types by automatically generating instances of these types when required within the project system. This means that no groovy classes have to be coded in order to take advantage of the definitions, and no stub code need be generated. Simply define a type and publish it, and Dipforge takes care of the rest.

Types are defined in the project_types.xml file of the project, and are defined in XML as follows:

<types project=”test”>

<type name=”type1″ namespace=”http://dipforge.sourceforge.net/test1″>
<property name=”id” datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<property name=”property1″ datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<property name=”property2″ datatype=”http://www.w3.org/2001/XMLSchema#string”/>
</type>

<type name=”type2″ namespace=”http://dipforge.sourceforge.net/test2″>
<property name=”id” datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<property name=”property3″ datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<property name=”property4″ datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<property name=”property5″ datatype=”http://dipforge.sourceforge.net/test1#type1″/>
</type>

<type name=”type3″ namespace=”http://dipforge.sourceforge.net/test3″>
<property name=”id” datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<property name=”property3″ datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<property name=”property4″ datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<link name=”property5″ datatype=”http://dipforge.sourceforge.net/test1#type1″/>
</type>

<type name=”type4″ namespace=”http://dipforge.sourceforge.net/test4″>
<property name=”id” datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<property name=”property3″ datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<property name=”property4″ datatype=”http://www.w3.org/2001/XMLSchema#string”/>
<link name=”property5″ datatype=”http://dipforge.sourceforge.net/test1#type1″/>
</type>

</types>

“Note: Found in the test project”

The XML is broken down into the following elements

  • types: This sets up the scope of the types and contains the rest of the element information. In the above example the type scope is simply “test”
  • type: As the name implies this contains the definition of the type. The element consists of  two attributes, the name and the namespace. A types full name is the concatenation of both the name and name space by a # for example “http://dipforge.sourceforge.net/test1#type1″ from the above example.
  • property: A property is a property of a type and consists of a name and datatype. The word property implies that the type owns the data defined by this property.
  • link: A link is similar to a property but this type only references the data it does not own it. This is important when changing data, because when a requested is submitted for an action on a type the update will only affect the types own properties and not the links.
When the types have been defined as per your requirements, simply click on the publish button provided by the editor, and the types will be published to the system and made available for consumption.
In order to access the types in groovy refer to the following example

import com.dipforge.semantic.RDF;

.

.

def test1 = RDF.create(“http://dipforge.sourceforge.net/test1#type1″)

test1.setId(“my own id”)
test1.setProperty1(“name”)
test1.setProperty2(“description”)

“Note: found in the test project”

ID Property

The ID Property is a special property. It is required in a type definition and can either be a string or an integer. It is used by the typing system to generate the unique URL for a type instance. If no value is supplied for it, a hash code will be generated for the ID value automatically by the typing system, that is if the ID is a of type string.

Below is an example of how the id property is used:

test1.setId(“my-own-id”)

.

http://dipforge.sourceforge.net/test1#type1/my-own-id

Controls

The controls are implemented as simple Groovy scripts and are the C within an MVC (Model View Control) pattern. Within the scope of the controller is is possible to access the RDF read store directly. This means it is possible to query and extract the data necessary to render a page using a view.

Below follows a simple example of how to query the store and to invoke a page:

import com.dipforge.utils.PageManager;
import com.dipforge.semantic.RDF;
import org.apache.log4j.Logger;
def log = Logger.getLogger(“test.index.groovy”);

def result = RDF.query(“SELECT ?s WHERE {” +
“?s a <http://dipforge.sourceforge.net/test1#type1> . }”)

PageManager.includeWithResult(“list.gsp”, request, response, ["tests" : result])

“Note: Found in the test project”

The above example performs a simple RDF select on the RDF store and then passes the data to the “list.gsp” page to be displayed. This is a very traditional way of rendering a page.

When a change is made to a type instance a request associated with the action performed must be made on the Workflow engine in order to affect the change throughout the Dipforge environment. This is done using the Request object.

import com.dipforge.utils.PageManager;
import com.dipforge.semantic.RDF;
import org.apache.log4j.Logger;
import com.rift.coad.lib.common.RandomGuid;
import com.dipforge.request.RequestHandler;
def log = Logger.getLogger(“test.index.groovy”);

def test1 = RDF.create(“http://dipforge.sourceforge.net/test1#type1″)
log.info(“Set the values on : ” + test1)
test1.setId(RandomGuid.getInstance().getGuid())
test1.setProperty1(params.name)
test1.setProperty2(params.description)
//test1.setProperty3(params.description)

log.info(“Init the request : ” + test1)
RequestHandler.getInstance(“test”, “test1″, test1).makeRequest()
PageManager.forward(“index.gsp”, request, response)

“Note: Found in the test project”

The above example creates an instance of the RDF type using the “RDF” object. It sets all the properties appropriately and then invokes a request on the on the Workflow engine using the RequestHandler.

RequestHandler.getInstance(“test”, “test1″, test1).makeRequest()

This creates a new request handler instance and sets the parent request up for the appropriate action on the test type instance. The parameters to the getInstance method are :

  • project name =”test”: This is the name of the project the flow or action is defined in.
  • action name =”test1″: The name of the action to perform. In this example it is simple test but that can be anything you like as long as it is defined in the “project_actions.xml”.
  • data =test1: This is the data the action needs to be performed on. 

To invoke this action the makeRequest method must be invoked on the request handler.

If a more complex process is required this can be invoked by calling createChild on the request handler instance. The parameters are the same as above and it must to be performed on the instance before calling makeRequest

def instance = RequestHandler.getInstance(“test”, “test1″, test1)
instance.createChild(“test”,”test1″,test2)
instance.makeRequest()

AJAX

If an AJAX approach is required it is easy to return a JSON object from the controller to the caller using Groovy’s built in JsonBuilder.

import groovy.json.*

def builder = new JsonBuilder()

def userFeeds = [
[
image: 'favicon.ico',
author: 'test',
msg: 'there is news',
url: 'http://news.bbc.co.uk/'
],
[
image: 'favicon.ico',
author: 'test',
msg: 'this is cnn',
url: 'http://www.cnn.com/'
],
[
image: 'favicon.ico',
author: 'test',
msg: 'there is skyjljljljl jljljljljlkl jljljljljljk xxxxx bbbbb dddd ccccc eeee ffff',
url: 'http://www.sky.com/'
],
[
image: 'favicon.ico',
author: 'test',
msg: 'there is skyjljljljl jljljljljlkl jljljljljljk xxxxx bbbbb dddd ccccc eeee ffff',
url: 'http://www.sky.com/'
]]

builder(userFeeds)

println builder.toString()

“Note: Found in the desktop project”

Daemon Access

The controllers can also make use of backend exposed daemon services. Dipforge does not implemented an EJB container framework instead it implements a Daemon container framework. All of these daemons are available via exposed API to the controllers if the caller has the appropriate user rights.

package applications

import groovy.json.*
import com.rift.coad.util.connection.ConnectionManager
import org.apache.log4j.Logger;
import com.rift.coad.daemon.event.FeedServer

def log = Logger.getLogger(“files.FileList”);
def feeds = []
try {
def daemon = ConnectionManager.getInstance().getConnection(
FeedServer.class,”event/Server”)
def events = daemon.getEvents(“environment”)
for (def event : events) {
feeds.add([
image: 'favicon.ico',
title: event.getName(),
author: event.getApplication(),
msg: event.getDescription(),
url: event.getUrl()
])
}
events = daemon.getEvents(“news”)
for (def event : events) {
feeds.add([
image: 'favicon.ico',
title: event.getName(),
author: event.getApplication(),
msg: event.getDescription(),
url: event.getUrl()
])
}
} catch (Exception ex) {
log.error(“Failed to retrieve the feed information : ” + ex.getMessage(),ex)
}
def builder = new JsonBuilder()
builder(feeds)

println builder.toString()

“Note: Found in the desktop project”

Views

The views consist of all the presentation files. This includes all GSP (Groovy Server Pages), HTML, Javascript, and images. Out the box Dipforge provides, EXT JS, Jquery, and Bootstrap. All these resources are provided in the Dipforge project as part of the views folder. These resources are transparently mapped into you project.

An example follows of how to use RDF in GSP, this example is called from the list.groovy controller we looked at earlier:

<%
import com.dipforge.semantic.RDF
%>
<html>
<head>
<title>list test</title>
</head>
<boby>
<h>Test data</h>
<table cellpadding=0 cellspacing=0 width=”100%”>
<tr>
<td>
id
</td>
<td>
property1
</td>
<td>
property2
</td>
</tr>
<%
params.tests.each { testdata ->
def data = testdata[0]
%>
<tr>
<td>
${data.getId()}
</td>
<td>
${data.property1}
</td>
<td>
<% print(data.getProperty2()) %>
</td>
</tr>
<%}
%>
</table>
<a href=”index.groovy”>back</a>
</boby>
</html>

“Note: Found in the test project”

Flows

Flows are implemented in Leviathan Script, and are configured via the “project_actions.xml“. This  file maps actions on dynamic types to the appropriate Leviathan Script.

<actions project=”test”>

<action name=”test1″ type=”http://dipforge.sourceforge.net/test1#type1″ file=”/flows/bob.lwf” role=”test” />
<action name=”test2″ type=”http://dipforge.sourceforge.net/test1#type1″ file=”/flows/test.lwf” role=”test” />

</actions>

“Note: Found in the test project”

The above example mapps actions onto the test type 1 for the role of test. Here is a break down of the elements in the xml.

  • actions: This contains the list of actions and defines the name of the project the actions are associated with.
  • action: The mapping this consists of the name of the action, the type the action is being performed on, the path to the appropriate Leviathan Script file, and the role required to execute the action.
Once the scripts have been implemented and the configuration completed, simply click the publish button to make the actions live.

Leviathan Script

This is a domain specific language designed to hide the complexity of developing asynchronous process and workflows. It provides the ability to rapidly develop business processes without the reliance on a heavy and cumbersome drag and drop tools. The language is similar in nature to both Java and Groovy but it aims to be as simple as possible for now.

Note: This section does not aim to teach programming but instead introduce the Leviathan Script language.

The language consists of the following elements:

  • annotations:  As with both Java and Groovy these are prefixed with an @. There is currently no way to extend these dynamically.
  • flow: The flow keyword defines a process flow like the word class defines a class.
  • def: Like in Groovy this defines a variant.
  • {}: The language uses braces like Groovy and Java and first set of braces opened within the scope of a flow identify the master flow.
  • methods: These are defined the same way as Groovy or Java “<return type> <name>(<type> <name>, …)”
  • =: The assignment operator.
  • if: Support for if statements.
  • for: Support for tradition for loops.
Here is an example:

/**
* This is the template for a flow
*/
@java(“out”)
@rdf(“http://dipforge.sourceforge.net/test1#type1″ “type1″)
@store(“store”)
@service(“test” “test” “test.TestClass” “test”)
@jndi(“groovy/DataMapper” “test” “test.TestClass” “test2″)
flow bob {
def out
def type1
def test
def test2
{
out.println(“before : ##################################################”)
out.println(“hello world example 1 : ” + type1.getProperty1())
out.println(“hello world example 2 : ” + type1.property2)
test.callTest1(type1.property2)
def type2 = test.callTest2(type1.property1,type1)
def type3 = test2.callTest2(“type1.property1″,type1)
type1.setProperty1(“man on moon”)
out.println(“hello world example 3 : ” + type1.getProperty1())
out.println(“hello world example 4 : ” + type1.property2)
out.println(“after : ##################################################”)
store.persist(type1)
}
}

“Note: Found in the test project”

The following annotations are used in the example:
  • java: Provides access to some Java objects. In this example it is providing access to the out object which is a wrapping for System.out. Another alternative is access to the log object. This provides the script a reference to the Log4j object.
  • rdf: The mapping of the RDF type to a local variable. Name of the variable has to match the name of the type and must be the same case.
  • store: This sets up the name of the variable to be used for the reference to the RDF master store.
  • service: Sets up a variable reference to an external service script. The annotation is configure as follows:
    @service(<service name> <project> <script class path> <variable name>)
  • jndi: Sets up a variable reference to an external service script identified by a JNDI binding. The annotation is configure as follows:
    @jndi(<jndi binding> <project> <script class path> <variable name>)

RDF Store

The RDF store used in the above example is responsible for managing the persistance of data to the Master RDF store. From the Master RDF store changes are pushed to the slave stores of which the frontend is one. This means that all changes have to go via the Workflow in order to propagate to the slaves.

The slaves can be horizontally loaded so as to improve read performance and scalability. The Master RDF store does not get hit for any queries it is purely there for backup and for managing the process of pushing changes to the slaves.

The API on the store consists of the following methods:

  • persist(<rdf value>): Save/Update the value in the store.
  • remove(<rdf value>): Remove the value from the store.

Services (JNDI and Service Name)

These are either annotated via the @service or via @jndi, and are references to the services responsible for implementing the end points. These are groovy classes configured through the file “project_methods.xml“. This provides a way to rapidly develop end points and attach them to flows by simple configuration.

Services

Services are Groovy classes that are scripted to match requirements and then exposed via the “project_methods.xml” file. Using groovy as the service layer provides a means to rapidly develop the end points that does not require a redeployment process,  as any changes the script are immediately live.

package test

class TestClass {

/**
* This is a test call.
*/
def callTest1(def message) {
println message
}

def callTest2(def message, def data) {
println message
println data.getProperty1()
return data
}

}

“Note: Found in the test project”

Once a script has been developed to match the requirements it is exposed to the Workflow engine through the ”project_methods.xml” file.

<mapping>
<jndi name=”groovy/DataMapper” service=”test”>
<project name=”test”>
<method class=”test.TestClass” name=”callTest1″ type=”http://www.w3.org/2001/XMLSchema#string”>
<parameter name=”message” type=”http://www.w3.org/2001/XMLSchema#string”/>
</method>
<method class=”test.TestClass” name=”callTest2″ type=”http://dipforge.sourceforge.net/test1#type1″>
<parameter name=”message” type=”http://www.w3.org/2001/XMLSchema#string”/>
<parameter name=”data” type=”http://dipforge.sourceforge.net/test1#type1″/>
</method>
</project>
</jndi>
</mapping>

“Note: Found in the test project”

The elements within the configuration file are the following

  • mapping: The contents of the file are contained in a mapping element.
  • jndi: A jndi element specifies the jndi name for the scripts, this will be “groovy/DataMapper” as it is the only support mechanism at the moment, and the service name. This service name is used by the Service registry as a lookup mechanism, and is generally associated with a functional grouping such as mail. In the above example it is set to test.
  • project: The project element sets up the project name.
  • method: This sets up the method mapping and consists of a class reference, this is the class name to use; a name this is the name of the method to invoke on the class; and a type, this is the RDF return type.
  • parameter: The parameter element defines the mapping for a method parameter, and consists of the name of the parameter and the data type for the parameter.

Packages

Packages consist of common utilities that can be reused. The Dipforge project exposes a bunch of these, but each Project can implement its own as the need arises.

Libraries

This is a folder that contains all the java libraries required by the project. There are a default set of libraries provided but if a particular project requires extra libraries not provided this is the place to put them.

Scheduled Processes

This provides the ability to schedule calls on scripts to execute at a particular time. The configuration for this is setup in the file “project_times.xml” . The configuration file looks like the following:

<times project=”test”>

<time jndi=”groovy/Timer” script=”test1.groovy” month=”1″ day=”1″ hour=”1″ minute=”1″ recur=”false” />
<time jndi=”groovy/Timer” script=”test2.groovy” month=”2″ day=”2″ hour=”2″ minute=”2″ recur=”false”/>

</times>

“Note: Found in the test project”

The elements for the configuration file are the following:

  • times: The container element for the list of times for this project. The name of the project the configuration is for.
  • time: The time information month, day, hour, minute; should this event re-occur; the jndi binding; and the path to the script.

All scripts must be implemented in the services folder.

Browsing Project

All projects are exposed via HTTP under the context of DipforgeWeb. In order to access the view open your browser at:

http://<hostname>:8080/DipforgeWeb/<project name>/

Default Index Page

Dipforge supports the following default page types:

  • index.html: A static page in the view folder.
  • index.gsp: A gsp view page.
  • index.groovy: A groovy controller.

Reverse Proxy

To control the mapping of projects into the frontend directly under / on the server Dipforge provides a reverse proxy. This proxy is currently not configurable through the frontend, and will require a restart in order for changes to take effect. The configuration changes are made through an XML file located with under the following directory:

<dipforge project>/release/dipforge/var/proxy/proxy_config.xml

The standard configuration file looks like the following:

<?xml version=”1.0″ encoding=”UTF-8″?>
<config>
<server className=”net.sf.j2ep.servers.BaseServer”
domainName=”localhost:8080″
path=”/AuditTrailConsole”
isRewriting=”true”>
<rule className=”net.sf.j2ep.rules.AcceptEverythingRule”/>
<rule className=”net.sf.j2ep.rules.DirectoryRule”
directory=”/desktop/AuditTrailConsole” />
</server>
<server className=”net.sf.j2ep.servers.BaseServer”
domainName=”localhost:8080″
path=”/manager”
isRewriting=”true”>
<rule className=”net.sf.j2ep.rules.AcceptEverythingRule”/>
<rule className=”net.sf.j2ep.rules.DirectoryRule”
directory=”/desktop/manager” />
</server>
<server className=”net.sf.j2ep.servers.BaseServer”
domainName=”localhost:8080″
path=”/DipforgeAdmin”
isRewriting=”true”>
<rule className=”net.sf.j2ep.rules.AcceptEverythingRule”/>
<rule className=”net.sf.j2ep.rules.DirectoryRule”
directory=”/desktop/DipforgeAdmin” />
</server>
<server className=”net.sf.j2ep.servers.BaseServer”
domainName=”localhost:8080″
path=”/FileManager”
isRewriting=”true”>
<rule className=”net.sf.j2ep.rules.AcceptEverythingRule”/>
<rule className=”net.sf.j2ep.rules.DirectoryRule”
directory=”/desktop/FileManager” />
</server>
<server className=”net.sf.j2ep.servers.BaseServer”
domainName=”localhost:8080″
path=”/DipforgeWeb/documentation”
isRewriting=”true”>
<rule className=”net.sf.j2ep.rules.AcceptEverythingRule”/>
<rule className=”net.sf.j2ep.rules.DirectoryRule”
directory=”/desktop/documentation” />
</server>
<server className=”net.sf.j2ep.servers.BaseServer”
domainName=”localhost:8080″
path=”/DipforgeWeb/ide”
isRewriting=”true”>
<rule className=”net.sf.j2ep.rules.AcceptEverythingRule”/>
<rule className=”net.sf.j2ep.rules.DirectoryRule”
directory=”/desktop/ide” />
</server>
<server className=”net.sf.j2ep.servers.BaseServer”
domainName=”localhost:8080″
path=”/DipforgeWeb/bss”
isRewriting=”true”>
<rule className=”net.sf.j2ep.rules.AcceptEverythingRule”/>
<rule className=”net.sf.j2ep.rules.DirectoryRule”
directory=”/desktop/bss” />
</server>
<server className=”net.sf.j2ep.servers.BaseServer”
domainName=”localhost:8080″
path=”/DipforgeWeb/desktop”
isRewriting=”true”>
<rule className=”net.sf.j2ep.rules.AcceptEverythingRule”/>
<rule className=”net.sf.j2ep.rules.DirectoryRule”
directory=”/desktop” />
</server>
<server className=”net.sf.j2ep.servers.BaseServer”
domainName=”localhost:8080″
path=”/DipforgeWeb/public”
isRewriting=”true”>
<rule className=”net.sf.j2ep.rules.AcceptEverythingRule”/>
</server>
</config>

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Home Documentation