Aug 29, 2015, 1:26 PM
453 Posts

Best Method to create an Order Entry like application

  • Category: Other
  • Platform: All
  • Release: 9.0.1
  • Role: Developer
  • Tags: java object
  • Replies: 9

I'm looking at building a system where a Main Document (say an Order Entry) that will have one or more line items associated to it. Each of the line items will contain several pieces of information such as part # Qty price etc. In Native Notes I have done something like this with a bunch of single value fields for each value Qty_1, Qty_2 etc. Not a pretty sight. 

1. In XPages I do something like this where I create a new document for each line then display them in the MainDoc using a repeat control. This works OK until in need to total the Qty * Price which means cycling through each of the sub Documents and multiply them together then add them up. 

2. My next idea is to create a viewscope Java Bean that would load the related documents onPageLoad then the bean could have a total method that should be fairly fast but not sure that is the best solution, would need to coordinate changes to line items in the bean with the underlying documents .

3. I have seen some discussions on storing the Bean directly in the MainDoc then retrieve it into the Bean onPageLoad which seems to me to be probably the fastest and most efficient method, but take the most time to develop.

I have previously developed a couple of different JavaBeans that would be somewhat like #2 solution, but storing the bean in the Notes Document puts me on another learning curve.

Any suggestions (examples) on best practice would be appreciated.

Aug 30, 2015, 11:00 AM
589 Posts
my thoughts on XPages Best Practices

Bill,

Don't do the mimeBean option in #3...  I think that has limited use cases overall.  By not using documents for the line items you'll lose some ability to easily get things like "How many times was this item sold last month" etc.  Also a big potential gotcha with the mimeBean stuff is if you want to modify the object AFTER the fact.  If you don't do it correctly you'll lose the ability to get to the previously saved beans.  DISCLAIMER: I've done very little with mimeBeans for these reasons. So maybe I'm missing something - but this is my understand of it.

You keep using the term "Bean" but not everything has to be a bean of course.  It could be just a POJO that you manage yourself rather then adding it to the faces config.... don't get wrapped up on "everything must be a managed bean"

Here's what I would do...

Note - I use Jesse's pageController stuff.  Once that's in place I'm good.  No additional facesConfig things needed... No more managed beans... for this piece at least.  Just keep in mind that when I talk about "pageController" all that really is, is a "managed" viewScope bean like you would manually make.  It's just not being managed via facesConfig.  It's being managed via Jesse's framework.  All it really does is allow you to match a page specific Java class to an xpage but refer to it on each xpage by a common name..  "controller" for instance.

I'd make an orderObject and an itemObject in Java.. I would use these exclusively and the XPage or Custom controls would NEVER talk to Domino documents or views directly.  You only talk to the objects and let the objects do the work

On an "Order.xsp"..  in the beforePageLoad of the "controller" I'd setup the new order object (default values... whatever)  or via url parameter load the values for an existing saved order.

orderObject inside would have something like 

List<itemObject> or maybe more likely Map<String, itemObject>  

with the appropriate getters and setters...

Now when you load the Order object...  yes you're going to loop through the lineItem Notes Documents and "convert" them into "itemObjects"...  

itemObject would have methods like getQuantity(), getTotalPrice() etc...

orderObject would have methods like addItem(), deleteItem(), getAllItems()

On the XPage itself to add a lineItem you might have a button:  Add Item which might look like (SSJS):

controller.addItem()

Now this gets back to the pageController... and again.. page controllers ROCK!!!! But you have to get used to them...

addItem method on the controller would create a new itemObject and maybe assign to it to a "currentItem" variable in the controller...  something like:

public boolean addItem() {

this.currentItem = this.objectItem.addItem()

}

But of course you might not want to render the Add Item button if the order is completed...  so the rendering/visible of that button might look like:

controller.orderObject.orderOpen

Which would map to "boolean isOrderOpen()" method in order object.  If true, the button shows... if false.  it doesn't...   you could call it isCompleted() but then you need to reverse the rendering...  or because you're now making you're own "API" you can have both methods for convenience.

Anyway....

Since the addItem method is going through the objectItem you can save an item to disk AND live add it to the internal Map/List at the same time...  rather then doing a refresh() and just reloading everything from disk.  You could also at this time if you wanted, increment a totalPrice variable inside the order object to have that handy.

On the XPage to get a hold of this to bind set the description field using EL it would look like

controller.currentItem.description

And of course you'd need to eventually write it back to the document via a method in the lineItem object

controller.getCurrentItem().save()     (I usually use SSJS for action methods though)

Now when you want to have a repeat showing each item the repeat would look like this in EL

controller.orderObject.allItems

and you're "rowData" would now be itemObects... so to display fields you just call the proper methods in EL

rowData.quantity

When you want to get the total price you have a couple options...  you could go the route of the totalPrice variable if you're storing that...  or you loop through your List/Map and just live calculate it.  Because you're dealing with in Memory objects now and not documents...  it'll be FAST....  of course if you get into the 1,000's then you might want to do the totalPrice variable thing...

 

There's more then a few "blanks" in what I've just described BUT this concept is how I'm doing all my applications these days and I believe this is absolutely the best overall way to develop XPages applications.  It's NOT THE ONLY WAY...  and it DOES REQUIRE JAVA...  it's just the best way.  Why is it the best?

Because all you're business logic lives inside it's own objects.  orderObject, itemObject.  These objects don't need to know about the UI...  or current state...  or anything like that.

You're UI logic is the page controller...  it talks to the business objects...  the controller worries about what to render..  who the user is...  etc...  It's MVC type stuff.

The XPage/Custom Controls are now CLEAN... there's literally NO logic on them.  They just call methods in the controller using EL or SSJS.  So the XPages content is reduced and much much cleaner.  

So all this becomes much easier to maintain and enhance.  I believe this is now the "Best Practice".

I've done several videos on this on NotesIn9...  At least enough to get going with an app...    Again - that was just a rough description but....

THIS IS A WONDERFUL WAY TO LIVE!!!  

 

Good Luck

 

Aug 30, 2015, 7:12 PM
453 Posts
Thanks David

Looked at the pageController and it looks interesting. Might just load a JAVA viewScope onPageLoad. using a LineObject and look after the writting the lines back out. Having access to each line as an actual document is almost a necessity.

I'm going to look further into the pageController.

Aug 31, 2015, 7:49 AM
589 Posts
Question

Why do you say :

"Having access to each line as an actual document is almost a necessity."

Except maybe in the case of dealing with attachments I don't see why you have to get a hold of the data document directly.  Now i will say I often do add methods like:

lineItem.getDocument()

just in case I do need to get to the real document.  But I almost never actually use those methods...

Just wondering..

Also - yeah it doesn't matter how you get to the object.  The controllers are nice because you can then bind the beforePageLoad and afterPageLoad events inside them.  But if you just loaded them into a viewScope variable you'd be able to access it easily enough I'd think

viewScope.myBeanName.companyName   - EL

viewScope.myBeanName.getCompanyName()   - SSJS

 

Aug 31, 2015, 10:45 AM
453 Posts
Why I want the line items as individual documents

I could then sort the outstanding items by say part number and be able to know how many of which part# I'm going to need, also produce back-order reports etc. 

Aug 31, 2015, 6:00 PM
589 Posts
hmm

Well of course I don't know your application Bill...

I convert all my documents to Java Objects.  When I want to sort them I can add "Comparators"...  There's a Comparable and a Comparator...  It's basically a method you add to the class.  Then you can either do a Collections.sort...  or you can add them to a sorted List or Set and they're automatically sorted.  And the best part?  You can have as many sorting methods as you want.  So now you have a lot of sorting flexibility without views!

Remember these objects eventually would get saved as documents...  that's where a back order report or something might come from I'd think.

Anyway - go with the Document if you want.. but I firmly believe that the "Best Method" for this type of app is by using the Java Objects to represent your documents.

Good Luck sir!  If you have any questions just let me know.

Dave

 

Sep 1, 2015, 1:04 PM
453 Posts
but

Once the Java object gets saved it is just another Notes Document though - is that not true?

Sep 1, 2015, 1:48 PM
291 Posts
I think you would just have to update/create the Notes docs in your Java save
I think to do what you want to do to apply a Java model would on open get all the child docs and maybe store the doc unid for each item document in a class, called OrderItem (along with all the other info. you need like qty, price, description, etc). Then your save could get the existing document(s), update/delete them or create a new document if a new item was added. Maybe even have a flag on the OrderItem class to indicate it was dirty (needs to be saved) to avoid un-necessary document writes.

You could then put the OrderItems in a Map to store them in Java. Having a method that returns a collection of OrderItems for that order would be good to be able to pass that to a repeat to display on the XPage.

Howard
Sep 1, 2015, 4:33 PM
589 Posts
Bill

You say :
"Once the Java object gets saved it is just another Notes Document though - is that not true?"

That's correct for the most part.  The Java object is the translator between the xpage and the document itself.  Technically you don't save the "Java Object".  The Java Object has a save method that will create or reload the notes documents and then save all it's internal variables to fields on the notes document.

The advantage to this is you can enhance your java object with all sorts of functionality.  Think of the NotesDocument backend object.  There's a getAllChildren() method or something like that. You can build your own.  getAllLineItems().  Very easy to do.  Very maintainable code!  

I believe Howard is basically saying the same thing I am.

I've been talking about this concept on NotesIn9 for a long time now.  There's been other people discussing it also.  

If you're confused by ANYTHING let me know here or ping me on skype.  I think there might be a little disconnect here that I'm not seeing.

 

 

Sep 2, 2015, 10:58 AM
453 Posts
I think my AppProps bean is sort of doing this

I have an applicationScope bean called AppProps and it loads a bunch of properties about each "application". So instead of doing this I would do something similar with the line items and store them in a viewScope. My class LineItems would have all the methods to manipulate the items. Using the LineItem UNID as the key. 

I'm not sure that I'm ready to go to a full Java application, but I'll consider that.

Thanks David and Howard for your thoughts and input. My brain has a hard time wrapping itself around this whole Java thing (20 years of Native Notes Development is hard to shake).

Bill