Getting Parameter List from PostgreSql Database

1
0
-1

Hello all,

First off, Happy New Year!

I am learning to use Bonitasoft, I've done the BPAD and Advanced Integration Courses, but quite frankly I still have A LOT of questions and A LOT to learn. I'm practicing by developing a group of Processes that require a set of pre-established parameters. I'm sure there are other implementations to solve this problem, in fact, I currently initialize these parameters by defining default values for my Business Data object. But, I would like to initialize this from a previously defined database that is NOT part of the process.

I have created the BDM object, it is a two item object with an integer ID and a text name. I then create a Process Variable using that object. Then I've tried to create a connector to initialize this Process Variable. I am trying to assign the values by defining the Output Operations as

PROCESSVARIABLE takes the value of tableResult.

I get a type mismatch in spite of both being java.util.List objects. Any clues?

Also, I don't get the option to use the graphical mode.

Thanks!

2 answers

1
0
-1
This one is the BEST answer!

Hi Luis,

Welcome, again I think, first yes there are lots of things to think about and this is a good starting point.

A set of predefined, single source parameters that you want to use for all processes...for example:

  • email server attributes
  • database server attributes
  • etc.

As you will have noted parameters are process based and not global so in this sense don't work. If I want to change the email server address then I only want to do it once not everywhere (for every process using live update).

For some reason this is still not built in when it should be... :)

OK, that's part 1 gripe out of the way.

My second gripe is the use of BDO/M. It's not always necessary. And in this case I feel it is definitely not required.

You have to ask yourself what are you using these parameters for, you don't say that in your post but I will use my example of email server attributes. These will never be shown on the screen (except in the configuration form) and will only be used by the process. Therefore not suitable for BDO/M just use them in the process as process variables.

Try not to over thing the use of BDO/M, when it is Business Data, sure use it if the data meets the explicit requirements of a BDO/M, i.e.

  1. You are recommended to use business data instead of process data for any data that has meaning outside of one single process.
  2. The business data objects are stored in a database that can be accessed by all applications and processes in a tenant.
  3. There is no need to import data from an external system or write it back after a change. The data is automatically stored persistently.

In my example of email server attributes I have two points that fail the BDM requirements:

Do my email server Attributes have meaning outside one process, tricky as this is a yes and no answer. Yes because I will use them, but more specifically because I will not base any business decision on them. They are what they are, they are fixed, unchangeable, unmodifiable, and do not form part of a process/business decision....

I do NOT want my email server parameters stored in all processes and made available to the all processes. Here for every process I would be saving a copy of the attributes in each process. Not what I need, and as Anna has found out will increase the size of database needlessly. Invoices can be stored and used by other processes, but my email attributes will not so attributes fail the test for a BDO/M.

So gripe 2 is use BDO/M appropriately, if there is any question of not meeting the requirement of a BDO/M then reconsider using a BDO/M.

gripe 3 is simple, I would like to see global parameters that act like a BDO/M but are not saved at all, which would suit the need for global parameters.

I will give you an example of how to do parameters, not database, but parameters file which will fit your needs:

  1. create pool variable for emParms as type map
  2. create a new connector Development->Connectors->New Definition
  3. give it a name getEMParmsfromProperties
  4. Next->Next->Next to Outputs
  5. Add a output emParms as type java.util.map
  6. Finish
  7. Development->Connectors->New Implementation
  8. Click the definition getEMParmsfromProperties
  9. Next
  10. Add the Class name to the end of the package name-> org.mycompany.connector.getEMParmsfromProperties otherwise you end up overwriting previous packages. :)
  11. Finish

Here you can now write your code to get your parameters from your source and return them as a map to your process

Here is some very bad sample code to

  • find the parameters file (under webapps/companyname/parameters folder)
  • Open the properties file
  • read the parameters
  • and save as a map.

NOTE: this code will not run as is, you have to write it as your own...

Note also that I use jasypt java library for de/encrypting our properties file...very important. Not necessary but very important.

You could rewrite this for SQL as required.

You then add this connector assigning the return to the previously created pool variable and then gain access to the data by referring to the returned map elements.

emParms.get("dbHost") etc.

Hope this helps,

regards
Seán

package org.mycompany.connector.DeleteImpl;

import org.bonitasoft.engine.connector.ConnectorException;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.properties.EncryptableProperties;

import java.util.regex.Pattern;

import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;

/**
 *The connector execution will follow the steps
 * 1 - setInputParameters() --> the connector receives input parameters values
 * 2 - validateInputParameters() --> the connector can validate input parameters values
 * 3 - connect() --> the connector can establish a connection to a remote server (if necessary)
 * 4 - executeBusinessLogic() --> execute the connector
 * 5 - getOutputParameters() --> output are retrieved from connector
 * 6 - disconnect() --> the connector can close connection to remote server (if any)
 */

public class DeleteImpl extends
AbstractDeleteImpl {

        String propertiesDir = "/webapps/?????????/properties/";
        Map<String, String> dbParms = new HashMap<String, String>();

        @Override
        protected void executeBusinessLogic() throws ConnectorException{

                 //preample code - preparation
                String catalinaHome = System.getProperty("CATALINA_HOME");

// allow for no catalina home or path in groovy runs from \bin\bootstrap.jar
// with Java ?
               
                String catalinaPath = System.getProperty("CATALINA_PATH");

                 if (catalinaHome == null && catalinaPath == null){

                         String strClassPath = System.getProperty("java.class.path");
                         
                         //20150201 new version to get to webapps - START
                         if (strClassPath.indexOf(";") != 0 ){

                                 //strClassPath is concatenated and must be reduced to one dir
                               
                                 String[] catHome = strClassPath.split(Pattern.quote(";"));
                                 for (String singleCatHome : catHome){
                                         
                                         if (singleCatHome.indexOf("bin") != 0){
                                                 String noBin = singleCatHome.substring(0, singleCatHome.indexOf("bin"));
                                                 
                                                 File f = new File(noBin+"webapps");
                                                 if (f.exists() && f.isDirectory()) {
                                                         catalinaHome = noBin;
                                                         break;
                                                 }
                                        }
                                }
                         }
                         else{
                                 //strClassPath is not concated and is OK?
                         }
                         //20150201 new version to get to webapps - END
                         
                 }
                 else if (catalinaHome == null && catalinaPath != null){
                         catalinaHome = catalinaPath;
                 }
                 else { // we have a CatalinaHome - but is it concatenated?
                         
                         if (catalinaHome.indexOf(";") != 0 ){
                                 //catalinaHome is concatenated and must be reduced to one dir
                               
                                 String[] catHome = catalinaHome.split(Pattern.quote(";"));
                                 for (String singleCatHome : catHome){
                                         if (singleCatHome.indexOf("webapps") != 0){
                                                catalinaHome = singleCatHome;
                                                break;
                                        }
                                }
                         }
                         else{
                                 //catalinaHome is not concated and is OK
                         }
                 }

                String propertiesFile = propertiesDir+"????DBEncrypted.properties";

                //set encryption
                StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
                encryptor.setPassword("");
                Properties propsEnc = new EncryptableProperties(encryptor);

                //inputs
                //none

                //outputs
                //sometimes added as global parms as in here

                initializeOutputs();

                //TODO execute your business logic here
                try{
                        try{
                                propsEnc.load(new FileInputStream(new File(catalinaHome + propertiesFile)));
                        }
                        catch(Exception e0){
                                propertiesFile = propertiesDir+"????DB.properties";
                                try{
                                        propsEnc.load(new FileInputStream(new File(catalinaHome + propertiesFile)));
                                }
                                catch(Exception e1){
                                }
                        }
                        try{
                                dbParms.put("dbType", propsEnc.getProperty("?????????Parms.dbType"));
                                dbParms.put("dbHost", propsEnc.getProperty("?????????Parms.dbHost"));
                                dbParms.put("dbPort", propsEnc.getProperty("?????????Parms.dbPort"));
                                dbParms.put("dbDatabase", propsEnc.getProperty("?????????Parms.dbDatabase"));
                                dbParms.put("dbUser", propsEnc.getProperty("?????????Parms.dbUser"));
                                dbParms.put("dbPassword", propsEnc.getProperty("?????????Parms.dbPassword"));
                                dbParms.remove("Default Null Output");
                               
                                //now to touch the database and make sure it is available
                                Connection con = null;
                                String url = "jdbc:postgresql://"+dbParms.get("dbHost")+":"+dbParms.get("dbPort")+"/"+dbParms.get("dbDatabase");
                                try {
                                        try {
                                                Class.forName("org.postgresql.Driver");
                                        } catch (ClassNotFoundException ex1) {
                                                dbParms.clear();
                                                dbParms.put("Error", thisModule+": DB Connection Error (ex1): "+ex1.toString());
                                        }
                                        con = DriverManager.getConnection(url, dbParms.get("dbUser"),dbParms.get("dbPassword"));
                                } catch (SQLException ex2) {
                                        dbParms.clear();
                                        dbParms.put("Error", thisModule+": DB Connection Error (ex2): "+ex2.toString());
                                } finally {
                                        try {
                                                if (con != null) {
                                                        con.close();
                                                }
                                        } catch (SQLException ex3) {
                                                logger.severe(thisModule+": DB Connection Error (ex3): dbParms="+dbParms);
                                                dbParms.clear();
                                                dbParms.put("Error", thisModule+": DB Connection Error (ex3): "+ex3.toString());
                                                logger.severe(thisModule+": DB Connection Error (ex3): "+ex3.toString());
                                                logger.severe(thisModule+": DB Connection Error (ex3):(catalinaHome): "+catalinaHome);
                                        }
                                }      

                        }
                        catch(Exception ex4){
                                logger.severe(thisModule+": DB Connection Error (ex4): dbParms="+dbParms);
                                dbParms.clear();
                                dbParms.put("Error", "dbParms Setting Failed (ex4): "+ex4.toString());
                                logger.severe(thisModule+": dbParms Setting Failed (ex4): Parameter failure, one or more parms is invalid."+ex4.toString());
                                logger.severe(thisModule+": DB Connection Error (ex4):(catalinaHome): "+catalinaHome);
                        }
                }
                catch(Exception ex5){
                        logger.severe(thisModule+": DB Connection Error (ex5): dbParms="+dbParms);
                        dbParms.clear();
                        dbParms.put("Error", "ResourceBundle get Messages Failed (ex5): "+ex5.toString());
                        logger.severe(thisModule+": ResourceBundle get Messages Failed: "+ex5.getMessage());
                        logger.severe(thisModule+": DB Connection Error (ex5):(catalinaHome): "+catalinaHome);
                }

                if(debug){d++; dumpDataOutputs();}

                //WARNING : Set the output of the connector execution. If outputs are not set, connector fails
                setDbParms(dbParms);

        }

        private void dumpDataOutputs(){

                logger.info(thisModule+": Ending: dataOutputs: "+dbParms);
                logger.info(thisModule+": End");

        }

        private void initializeOutputs(){

                //set default outputs
                dbParms.put("Default Null Output", "Default Null Output");
                setDbParms(dbParms);

        }

        @Override
        public void connect() throws ConnectorException{
                //[Optional] Open a connection to remote server

        }

        @Override
        public void disconnect() throws ConnectorException{
                //[Optional] Close connection to remote server

        }

}

1
0
-1

Thank you Sean!

I totally see your point about appropriate use of Business Data!

The parameters are items such as Priority, Order Type, etc. So they are short lists of parameters to use in forms with a name and an id. The Id is an integer that may be used in the future but I think I can simply put conditions where for example in priority: Urgent has an Id 5, I can then manipulate data to get indicators and such.

I will look at your response in greater detail and see how I can implement it.

Comments

Submitted by Sean McP on Fri, 01/08/2016 - 21:08

Thanks Luis,

as I can see it your use of parameters such as Priority, Order Type, etc. fall into both categories.

They are defined parameters that are unlikely to be changed and as an object in their own right, do not need BDO/M.

BUT the Object that uses them, as part of their "build" does need the index to them.

So as a parameter they are (selectable)

priorityId
priorityDescription

but as a Business Object they end up being used (in Delivery data (object)) as follows:

deliveryId
orderId
deliveryAddressid
deliveryPriorityId (index to priorityId)

In the process you want to save the Delivery data as an Object, but not the selectable priority.

This to me is the more correct way of using Business Data...Data Definition is a very new subject and quite complex to get right. One mans joy is another mans sorry if you understand the meaning...everything has two views....

regards
Seán

Submitted by lefloresg on Fri, 01/08/2016 - 23:09

Exactly, I would try to avoid nesting, but in the end, the more complex the "problem" you want to solve, the layers are bound to be added. Add to that, parameters may change in the future, and you don't want to have to go in to EVERY instance to change say a list of order types, rather just change it outside once.

The learning curve is proving challenging, and it's not just some knowledge in Java needed. I've found that to make a powerful tool it requires good knowledge in several fields. All in all though, I love the potential I see in Bonita. I don't know how much other BPMS differ from this though.

Submitted by lefloresg on Fri, 01/08/2016 - 23:51

Your comment has made me think, though, whether it makes more sense to simply store objects with the text/integer value, and simply have a script that translates the name for example to a number when ever I need to do any computing of data analysis. Then each object doesn't get an embedded object in it, but rather sure referential value that is a simple variable type!

Submitted by Sean McP on Sat, 01/09/2016 - 06:24

This is called Normalization in the database world. See here:

https://en.wikipedia.org/wiki/Database_normalization

And yes, you need to know more, much more than just java... :) As I've learnt.

Huge potential, yes. It's just envisaging it.

regards

Notifications