4
votes

Transitioning to XPage development with Java only. I've successfully put together a XPage with a form and bound all UI components to a managed bean. I created a save method in the bean. I am able to Submit the XPage, a document is created and the browser displays the XPage after the full refresh with the current values in the Bean. If I click Save repeatedly, a new document is always created, the first document that was created was never updated.

My question, what is the proper way to map the XPage to the current document so the bean always updates the document rather than always creating a new one?

Should I create a Bean member Document so the first time the document is saved, I keep a handle to it? does that mean I do not recycle the doc object after creation?

Should I lookup the doc every time when saving the unid? Performance issue?

Any one have a good programming pattern? Using Notes 9, no data source defined on the XPage.

4
Are you using a "button" or "submit" button? Also are you redirecting to the next page from there? I am using the button type, and it works fine. I also have a method for clearing all data which sets all Strings to "", ints to 0, etc. I run this prior to editing.Steve Zavocki
Using a Submit button type. Not redirecting to another page. Should I be?xpagesbeast
Try changing to button, and see what happens. Also try making a method to clear everything, you will need one when using managed beans.Steve Zavocki
Also, to answer your performance question, the backend java processing seems extremely fast in comparison to using SSJS, but I don't have benchmarks to prove that.Steve Zavocki
I've decided to create a private String docuid member in my Bean. The button calls in EL entryForm.save, I then check to see if docuid is null or empty. If so, I create a document. If docuid is not empty I do a database dot get document by universal id. My XPage has dates, numbers, and they save into the appropriate fields in the document in the correct data type. That was super simple to do and I think I'll stick to this until there is a better way.xpagesbeast

4 Answers

4
votes

You cannot have a Document member as this is not serializable, while a bean must be (depending on its scope, and the persistence options of the NSF). Moreover, the Document becomes invalid after the request completed, which means that you cannot safely keep it in the bean. Your bean has to own a reference to the Document so it can load/save it on demand, for example when your save() method is called. If your bean is making a copy of the data, then you should recycle() the Document as soon as possible, typically after loading the data and after saving them. A bean is not notified when it goes out of scope, or when the request is done. So it cannot safely manage the lifecycle of the resources it holds. A great data source to look at id the ObjectData in the extension library. This handles all the lifecycle management for the object (Java or JavaScript) so you can focus on the business logic.

1
votes

Ok, a couple of things in play here.

First, I totally agree with the concept of going for a real MVC pattern using Java. I am currently working on a project where the data model is approx. 30 entities where I am trying to implement a proper MVC pattern. I have had great inspiration from a series of 5 articles from Pipalia. The first is: http://www.pipalia.co.uk/notes-development/rethinking-xpages-part-one/ - and you should be able to find the next 4 on their site.

Basically, I have an XPage that only references a View bean (which is a managed bean - session scope). The View bean uses a facade layer (other names: CRUD, service) to do its data operations. However, the facade layer does not directly talk to the database. It uses an interface to define a DAO (Data Access Object) object, which is a Domino implementation of data access. This is the only class that knows how to talk to a Domino database. It will get a handle to the database, view, and document - read the data into a Data bean (which just holds fields with setters and getters) and then discard those Domino objects correctly again. After data has been read they live in the Data bean in memory. Only if I change data I will need to call the facade layer to validate and save (through the DAO layer).

In the XPage I will use EL to connect a field to data using something like: ViewBean.person.name (assuming the view bean was ViewBean and its data bean was person and the field was name). I then control whether I create a new person object in the View bean by creating an empty person object.

As a side note I have decided to use the OpenNTF Domino API so that I do not need to take care of recycles and have a much more modern Java implementation (e.g. use maps for creating new documents and better iterators, etc. etc.)

/John

0
votes

Building on what Philippe said about the bean lifecycle, I think you might be better suited using a plain old java object (POJO). Then you can control when the bean is instantiated. It works just the same, extra you have to create it and recycle it yourself.

In my project, I had the opposite problem where I wanted multiple documents but could only create one when using a managed bean. When I changed it to a POJO, it worked great. I controlled the creation of the new object.

I created the object in SSJS like as follows. It works great, and makes me think that in the future, I might just do everything this way.

var s = new com.mycompany.Shipper(requestScope.field1, requestScope.field2, requestScope.field3, requestScope.field4, UNID1, UNID2);
s.saveShipper(POdata);
0
votes

If I understand it correctly, the reason it's creating a new document each time is because your bean has no concept of which document it's dealing with. With a dominoDocument datasource on the XPage, this is handled by the action and documentId properties of the datasource. So calling a save method on that datasource not only saves to the backend database, it also updates those action and documentId properties of the datasource. As a result, any future action knows which document it should be acting on, because the documentId has been changed from an empty string to the UNID of the backend document that was created. Also the action has been changed from "createDocument" to "editDocument".

If you're using a bean, your save method needs simulate that process, setting variables for which document to act on. Then your save method needs to check if that property has a value, in which case retrieve the relevant document, otherwise create a new one. Otherwise your bean can only ever create documents, it can never update them.

Unless you're using the xe:dataObject, you also want to avoid using button of type submit. The beans don't know what to do with it. John will be ale to confirm, but I don't know if MVC will know what to do with it. xe:dataObject has a specific saveObject property so it does. It's easier to just use a normal button and on the Events tab, point it to the relevant save method.

Whether using beans, the xe:dataObject or MVC, you'll still need to tell the code when to create a document and when/how to retrieve one for update.