Retrieving ID from BDO for cumulative ID labeling

Hello everyone!

So, new question. I have an object with several objects. This is object is an array with several instances and it is specific to the current user. In other words, I will go and initiate the object the first time I use the app, everytime I use the app I will be adding items to the object each of them with a unique ID. This ID should be incremental, so I’m trying to write the code so that when I map my input from my form, I will add to the last ID. Example:

First time I use the app I make 3 objects therefore the objectId is 3. The next time I open the app and run it I want the objectId to start at four. This is the code I’m using:

This is the structure of my object

Object
- objectId
- userName
- attribute1
- attribute2
- etc

//Creating a list filled with object List objectInstance = objectDAO.find(0,10000); //Defining the last item in the BDO int lastObjectNum = currentObject.size(); //objectId is a string so transforming last item number into string to query value String lastObject = Integer.toString(lastObjectNum) //Retreiving objectId actual value for objectId in BDO String lastObjectId = objectDAO.findByObjectId(lastObject,0,10000).objectId; //Parsing string to get actual integer value to add new ID numbers int numId = Integer.parseInt(lastObjectId.trim()); //Initialize value that will define objectId of new items int i = 0; //Verify if there are older items in the collection if (numId==0 || numId<1){ //If empty collection initial value is one i = 1; } else { //Else if collection is not empty it takes the value of the last item i = numId; } //Setting object Id object.setObjectId(""+i);

With this code I’m getting an error: java.lang.NumberFormatException: For input string: “

Any help would be appreciated!

Thanks!

1 Like

I cannot really understand the logic of your code to generate your id.

But what I would recommend is to reuse the persistenceId attribute available on all business objects.

I create a diagram that I think demonstrate how to achieve what you are looking for.

I define an Invoice business data with two attributes:

  • creator (Long): the id of the Bonita BPM user who create the invoice
  • id (Long): invoice id that is unique for a given user (multiple users will have invoice with same id)

An additional attribute is automatically added by Bonita Business Data Model:

  • persistenceId (Long): this attribute is automatically incremented for each Invoice created (unique for all invoices)

The process definition have a reference to the newly created invoice. I use a groovy script to create the Invoice object in the default value of the reference.

I use Bonita BPM Engine API to find the id of the user who create the process instance and store this information in creator attribute of the Invoice object.

To generate a unique id per user for the invoice I use a Business Data Model custom query that search for the current user maximum invoice id value:
SELECT COALESCE(MAX(i.id), 0)
FROM Invoice i
WHERE i.creator = :creator

COALESCE function is the solution to return 0 by default in case of no invoice already exist.
Search query require one input: creator id

In order to make sure that this remain efficient I define an index on creator and invoice id.

The search query is called from the Groovy script using the variable invoiceDAO available from Groovy editor drop down list “Select a provided variable…”

On the first step form I display all (actually limited to 100) created invoices.

If you run the process from the Studio (deploy and create one instance) and then use “Processes” menu to start multiple instances with various users (e.g. helen.kelly with password bpm) you will see that id per user is actually incremented individually.

So this seems to be working and it turned out to be a lot simpler for this specific case. It helped to recognize that the number would equal the number of instances in the array plus one. So I wouldn’t actually have to read the value for the ID, this means I could even make it a more complex string ID!

Anyway, thanks for all your help! Let me know if you see any potential errors or better ways of writing this code!

String currentUser = ""; currentUser = BonitaUsers.getProcessInstanceInitiator(apiAccessor,processInstanceId).userName; List currentBDO = detailWeekObjsDAO.findByWkObjUser(currentUser,0,100); int lastNum = currentBDO.size(); int i = 0; if (lastNum ==0 || lastNum<1){ i = 1; } else { i = lastNum+1; }

A small hint here. Don’t use the “code” buttons above they don’t work as you can see,

Start code blocks with < code > and end with < /code > removing the spaces and it will format the code correctly

Antoine,

Thank you, I have cleared up the code I hope it makes more sense now. I don’t use persistence Id because I am creating a unique id for each user.

Thanks!!

Sorry but your use case is still not very clear to me.

My understanding is that:

  • Each users of the platform will have a set of Object associated with them.
  • Each time they start a process, the process will initialize a reference to this list
  • Also the process instance will add an element at the end of the list
  • Each object as an id that is unique for a given user (can be the same for two different user)

Is that right?

Maybe if you share your process that can help.

Thank you for your patience Antoine. The entire process is some what larger so sharing it may not be the most effective way. I will try to pose an analogous example.

The organization has x number of sales people. The process is made for each of them to create invoices. Rather than creating an instance of the object per each user, it is setup that all invoices are created in the same object simply distinguished by the user name on each instance. Each invoice also has an Id attribute which is sequential and unique to each user. So for example:

InvoiceNumber__InvoiceCreator__InvoiceID
1_____________Luis___________0001
2_____________Luis___________0002
3_____________Antoine________0001
4_____________Seán__________0001
5_____________Seán__________0002
6_____________Antoine________0002
7_____________Luis___________0003
8_____________Luis___________0004

The InvoiceNumber could be linked to the PersistenceID, but I would like the InvoiceID to be incremental according to each user. So if Antoine, opens the process again, the new instance of the invoice would create an InvoiceID 0003. Due to the analysis I hope to do afterwards I want this distinction and for ALL the invoices to be in the same database.

So from the process stand point, I want the Groovy script to go into the saved database, query the search by current user and then find the last InvoiceID and increment from that point. If the user has not created an invoice, the InvoiceID starts from 0001.

I hope this makes more sense. Thank you for your time!

Hi Luis,

my advice. Change the design. It will not work like this for long and will be a real PITA to modify later.

I remember working on something like this about 20 years ago completely unrelated to Bonitasoft, in COBOL if I remember rightly.

The easiest solution without too much effort would be to change the InvoiceID to something else like a Datetime field. It will always in in sequence for the salesman in question and no need to “work out the number”.

Otherwise I would do what nearly everyone else does:

BDM for Invoices
BDM for Sales person

Create a relationship between them

Years of other peoples knowledge has gone into this structure, why change it?

regards
Seán

or use the example that Antoine posted :slight_smile:

Seán, thank you for your comment. The invoiceId is just an example, I’m sure there are other cases where you may want to add onto a number that you have already stored in a BDO. I will try Antoine’s solution and see how it works out for me. All in all, beyond the specific functionality of my current application, I thought it’s an interesting problem to solve.

Antoine, I’m downloading Bonita 7.1.5 and as soon as possible I will try to apply your solution! Thanks for the follow up.