Apr 04

After deploying a new process I sure that you would like to run it ;)

It’s easy. First of all, you must create a new process instance:

        jbpmContext = jbpmConfiguration.createJbpmContext();
        processInstance = jbpmContext.newProcessInstance("processname");

Then you can initialize it by adding some variables to the process:

        contextInstance = processInstance.getContextInstance();
	contextInstance.setVariable("var", myVar);

To start it you have to send a signal to the process first token :

	processInstance.getRootToken().signal();

		

Related Posts

Mar 17

Deploy a process via java program not using Eclipse interface is very easy. You only need to write this lines.

JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();

ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("org/xxx/definitions/yyy/processdefinition.xml");

jbpmContext.deployProcessDefinition(processDefinition);

jbpmContext.close();

It is very useful when you have to write a setup program for your application.

Related Posts

Mar 14

jBPM Task node

jBPM task nodes are designed to interact with users. The main utility of this kind of nodes is to treat forms data. When a process arrives to a task node, it waits until the required actor makes an action.

Task nodes are the most complex nodes, you will have to implement two handlers: one to assign the task to an actor and another to define this task.

Lets start with the AssignmentHandler.

Using Eclipse interface you can setup your task node as it follows, specifying where is your class.

jBPM AssignmentHandler

ExampleAssign must be something like that:

public class ExampleAssign implements AssignmentHandler{
....
}

Implementing this interface means that you will have to develop an assign method.

public void assign(Assignable assignable, ExecutionContext executionContext) throws Exception;

Inside this function you will need to assign the current task(assignable) to somebody using assignable.setActorId(actor).

The responsibility of this method does not finish here. When you came into a task node, you will have to save all process state and variables to stop the process. You can not assume that the actor will be waiting for the assignment and neither you will want to wait until he logins into the application. System must continue running normally.

Calling this two functions you will save the execution context into database using Hibernate.

executionContext.getJbpmContext().save(executionContext.getTaskInstance());
executionContext.getJbpmContext().close();

Next step is to configure and develop a task controller.

jBPM task controller config

This class must look like this:

public class ControlExample implements TaskControllerHandler{
...
}

It must implement this two methods:

public void initializeTaskVariables(TaskInstance taskInstance, ContextInstance contextInstance, Token token);
public void submitTaskVariables(TaskInstance taskInstance, ContextInstance contextInstance, Token token);

First one is used to initialize task variables, you can set default values or whatever you need.

Second one treat all task variables. This is the main function of the task nodes. Remember to invoke token.signal(); when all treatment is done.

Thats all, but you will be wondering how does it work, how can I wake up the sleeping process…

Somewhere in your program, in a from treatment function or in a button event, for example, you will have to make some extra work. You will need to identify the user and the process instance. Functions like:

 List l = jbpmContext.getTaskMgmtSession().findTaskInstances(user);

will help you. When you have the correct TaskInstance you will have to invoke ti.end();. This function will wake up the process and the associated state from database using Hibernate and call submitTaskVariables(). Workflow will continue normally at this point.

Thats all I wanted to explain of jBPM nodes. I’m not normally using Fork and Join nodes in my projects, so I will not write a guide for them. They are very easy to include in your workflows but if somebody ask for it, I will write a mini how-to.

Related Posts

Feb 15

jBPM mail node

jBPM mail nodes are simple nodes designed only to send mails. This time you don’t have to implement any handler or function, jBPM libraries provide nearly all you need.

In mail info tab you can set the destination e-mail address, the subject and the mail body that is going to send. This will be useful when you know destination e-mail address, orders@mycompany.com, for instance.

If you need to send mails to workflow actors, you can set a user variable in context:

executionContext.setVariable("user", workflowActor);

and configure mail info as it follows:

jBPM mail info

jBPM address resolver will check for user e-mail address from database and send him the mail, you will have to do nothing!

This is a great node but I had some requirements that it didn’t provide to me, so I re-implemented it, adding some new methods.

You can download new implementation here.

Now I can send mails using a gmail account. To explain it in a simple way, my implementation read some extra parameters from jbpm.cfg.xml file before sending the mail.

  <string name="jbpm.mail.smtp.host" value="smtp.gmail.com" />
  <bean   name="jbpm.mail.address.resolver" class="org.jbpm.identity.mail.IdentityAddressResolver" singleton="true" />
  <string name="jbpm.mail.from.address" value="yourMail@gmail.com" />
  <string name="jbpm.mail.user" value="yourUser@gmail.com" />
  <string name="jbpm.mail.pass" value="yourPassword" />
  <string name="jbpm.mail.port" value="465" />
  <string name="jbpm.mail.smtp.socketFactory.port" value="465" />
  <string name="jbpm.mail.smtp.socketFactory.class" value="javax.net.ssl.SSLSocketFactory" />
  <string name="jbpm.mail.smtp.auth" value="true" />
  <string name="jbpm.mail.smtp.starttls.enable" value="true" />
  <string name="jbpm.mail.debug" value="true" />
  <string name="jbpm.mail.smtp.socketFactory.fallback" value="false" />
  <string name="jbpm.mail.advanced.config" value="true" />
  <string name='mail.class.name' value='FastSign.mail.Mail' />

If jbpm.mail.advanced.config is set to false it works as the original mail node. Setting it to true, activates the extra parameters. In this case, 465 is gmail port, I suppose you can change it to use other system. Note that you have to define mail.class.name with the correct package.

I hope this will be useful.

Related Posts

Feb 14

Decision node

jBPM decision nodes are very useful to create some alternative path along the workflow. The implementation of this node will choose the correct way.

Decision node example

To program these kind of nodes I prefer to develop a DecisionHandler rather than using an expression.

public class Validacion implements DecisionHandler{
....
}

Implement a decide method is mandatory:

public String decide(ExecutionContext executionContext) throws Exception;

Among this function code lines you can query database, consult session or recover variables from execution context:

executionContext.getVariable("previouslySetVariable");

This function must return a String containing the name of the transition to choose.

As the other nodes, you must configure the handler class with the node using Eclipse interface.

Decision node configuration

Related Posts

Feb 14

jBPM node

jBPM simple nodes are the most common nodes in all processes. They are used to encapsulate an action of your workflow.

The easiest way to program these kind of nodes is to develop an ActionHandler . You must do something like this:

public class Example implements ActionHandler{
.......
}

Developing ActionHandler interfaces involves to implement an execute method:

public void execute(ExecutionContext executionContext) throws Exception;

Inside this function you can add all code you need to perform the desired action. Remember that you have to send a signal to navigate to the next node at the end of execution.

executionContext.getProcessInstance().signal();

Finally, using Eclipse interface you have to link you node with you handler.

Action

At Action menu you must check Configure Action (your node must be selected). Inside Details tab you will be able to select and configure your class.

jBPM node Details

As easy as you read.

Related Posts

Feb 11

Moodle provides to developers an extensible user authentication library. You only need to extend auth_plugin_base class and place your code in a new directory inside /auth/. You can find this class inside /lib/authlib.php

This interface defines all functions you will need to develop a new authentication plug-in.

function user_login($username, $password);

This is the primary function used to login users into Moodle. You can do what you need in this function to finally return a boolean indicating the matching or mismatching of the given username and password.

funtion change_password_url();

This function must return the url where users can change the password. can_change_password() function must return true to call this one.

funtion is_internal();

Returns true if Moodle database stores user profile. For instance, LDAP plugin returns false.

function user_exists();

This function is used to check if user exists in external database.

function get_userinfo($username);

Returns an array containing all user information available.

function config_form($config, $err, $user_fields);

This function prints a form for configuring your authentication plug-in. validate_form() and process_config() functions will validate and store into database the introduced parameters.

There are other interesting functions but I have no time to explain all of them.

This interface also defines some hooks to specific Moodle pages.

Function loginpage_hook() allows to make some extra work before Moodle’s login page being printed. You can use it, for instance, to skip login form. You can check for another session in another platform to avoid users login twice.

I hope these lines will help you.

Related Posts

Feb 10

This is a usual question of all beginners.

ownerid, userid and groupid are set to wiki_pages table to differentiate them when any combination of groupmode or studentmode is set.

userid is a foreign key to Moodle users table. It contains the user id who edited that wiki page version.

If the current wiki is a separated groups or a visible groups activity. groupid is set to distinguish a page called “Moodle”between the several course groups.

ownerid is used to set a property relationship between the user and a wiki page. This is needed when any student mode is set and we allow users to edit pages belonging to other people.

Related Posts

Feb 10

This is a mini how-to oriented to new NWiki developers who usually use incorrect SQL queries to access to wiki pages.

wiki_pages table has one primary key: id. If you have it, you can invoke dmllib.php functions such get_record

	$page = get_record('wiki_pages', 'id', $pageid);

Several problems appear when you don’t have this id. Then you must use wiki API. There are great magic functions that recover wiki pages data from database.

If you are developing new features you must take into account that wiki_pages table has an enormous unique key:

  • pagename
  • version
  • dfwiki
  • groupid
  • userid
  • ownerid

In a normal situation you will have a pagename and a wiki id or a coursemodule id. Then, you must get coursemodule description using Moodle API.

  • get_coursemodule_from_id( $modulename, $cmid, $courseid);
  • get_coursemodule_from_instance($modulename, $instance, $courseid=0) ;

Using these functions you will be able to look up for the groupmode of this activity instance. At this point you will know the groupmode and stundentmode combination that is set up.

Calling get_record/s with the correct fields will return the desired wiki/s.

Related Posts

Jan 24

This is a guide for NWiki developers that explains step by step what they have to do if they want change NWiki database schema.

1. Changing installation file

mod/wiki/db/install.xml defines NWiki database schema. This file is used during NWiki installation. It’s necessary to modify this file according to the new development.

Adding a new field is an easy job, you only need to write a line. Be aware of the fact that every field defines which is the previous and the next field, so don’t copy an xml item only modify the name.

Adding a new table or a lot of fields more hateful. I recommend to use XMLDB editor that provides Moodle. You can access to this tool from admin block.

2. Changing NWiki version

mod/wiki/version.php contains module version. You will have to change $module->version to a new one. Version numbers are dates, so version format is YYYYMMDDVV, where YYYY is the current year, MM is the current month, DD is the current day and VV is the version number.

If I would need to change version today I would modify:

	$module->version = 2008012401

Creating several versions a long the same day increments VV. Next version would be:

	$module->version = 2008012402

3. Changing upgrade script

mod/wiki/db/upgrade.php contains NWiki upgrade script. This file defines what actions must be done into database to upgrade it. This process is used when a previous version of NWiki or Moodle old wiki is installed in your system.

The objective of xmldb_wiki_upgrade function is to modify database to set it as a new installation. In other words, executing upgrade script must create the same schema defined in install.xml.

You must add conditional blocks at the end of the file such the one below these lines to alter NWiki tables:

	if ($result && $oldversion < 2008011401) {
		$table = new XMLDBTable('wiki');
		$field = new XMLDBField('notetype');
		$result = $result && drop_field($table, $field);

		$field = new XMLDBField('evaluation');
		$result = $result && drop_field($table, $field);

		$table = new XMLDBTable('wiki_pages');
		$field = new XMLDBField('evaluation');
		$result = $result && drop_field($table, $field);

	}

$oldversion is the current NWiki version installed in your Moodle. You must compare it with a version number. If the condition matches, modifications will be done. To alter database schema you must use XMLDB API defined in lib/ddllib.php.

4. Course backup

If the modifications in database have repercussions in course backup, mod/wiki/backuplib.php must be adapted to create backups with the correct information.

Is possible to forget about this step if, for example, you modify wiki_locks table, creating backups of this table is useless. If you add or remove field from, for example wiki_pages, backup script must be corrected.

4. Course restore

If you modified backuplib.php, you will have to modify restorelib.php too. This file contains the script that restores wiki instances from a backup.

5. Nwiki xml import/export

NWiki also provides xml import & export scripts. They only backup content into xml files, so if you have modified wiki, wiki_pages or wiki_synonyms tables you must adapt this process to your changes.

Thats all folks! As you can see, changing database schema is not trivial, it implies a lot of work, programing and testing.

Related Posts