inputText onchange event not called after inactivity - xpages

I have a typeahead enabled on an inputText field which triggers an onChange event. This works fine unless the page has not been refreshed for a period of time (in testing, it stops working after 1 hour but may be less). Refreshing the page completely fixes the issue.
The code for the inputText field is as follows;
<xp:inputText id="quickSelectEntry" style="width:170px;">
<xp:this.dojoAttributes>
<xp:dojoAttribute name="placeHolder" value="Enter name">
</xp:dojoAttribute>
</xp:this.dojoAttributes>
<xp:typeAhead mode="none" minChars="2" ignoreCase="true"
var="searchValue" valueMarkup="true">
<xp:this.valueList><![CDATA[#{javascript:return nameTypeAhead(searchValue)}]]></xp:this.valueList>
</xp:typeAhead>
<xp:eventHandler event="onchange" submit="true"
refreshMode="norefresh">
<xp:this.action>
<xp:actionGroup>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:var searchVal:string = getComponent("quickSelectEntry").getValue();
if (searchVal.substr(0,1).equals("?")) {
context.redirectToPage("xCheckSecurityGroup.xsp?group=" + searchVal.substr(1));
return false;
} else {
var doc:NotesDocument = quickLookupView.getDocumentByKey(searchVal, true);
if (null != doc) {
viewScope.lookupKey = doc.getUniversalID();
viewScope.lookupForm = doc.getItemValueString("form");
return true;
} else {
viewScope.lookupKey = ""
viewScope.lookupForm = ""
return false;
}
}
]]></xp:this.script>
</xp:executeScript>
<xp:actionGroup>
<xp:this.condition><![CDATA[#{javascript:viewScope.lookupKey != ""}]]></xp:this.condition>
<xp:openPage target="openDocument"
documentId="#{javascript:return viewScope.lookupKey}">
<xp:this.name><![CDATA[#{javascript:return "x" + viewScope.lookupForm + ".xsp" }]]></xp:this.name>
</xp:openPage>
</xp:actionGroup>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
So far I've tried doing a timed partial refresh of the containing panel with no joy, I've set the typeahead mode from none to full. No difference.
Aside from refreshing the page every 10 minutes, is there anything else that couple be causing the problem. FYI The actual typeahead is working correctly consistently, its just the onchange event that stops firing.

What seems to happen is that the server web session is intact but the XPages session is lost.
Add the following to the bottom of your XPage and what it will do is refresh the DIV preiodically based on your setting (in milliseconds) (300000 = 300 seconds = 5 minutes) - the longest I have had a successful test is 3.5 hours.
You need to set a value at least one minute less than the session timeout length set in the application properties for your database.
<xp:div id="keepSessionAlive"></xp:div>
<xp:scriptBlock id="scriptBlock1">
<xp:this.value>
<![CDATA[
XSP.addOnLoad(function(){
setInterval(function(){
XSP.partialRefreshPost("#{id:keepSessionAlive}", {});
}, 300000)
})]]>
</xp:this.value>
</xp:scriptBlock>
Do not set a short refresh time as this will needlessly waste bandwidth and also bloat IE's RAM usage which is not well managed by the browser.
Understand that this is a SECURITY ISSUE at the same time - by basically keeping an idle computer's session alive you leave it open to hijack without the user's knowledge - that is the part of the point of a timeout

The issue is that the XSP session times out (according to your server settings). See this answer for recommendations on keeping the session alive:
How do I refresh page automatically when partial refresh doesn't work?

I have seen this too. I ended up putting in a meta refresh tag to reload the page every 30 minutes. It was the only thing that seems to work.
Howard

May want to check the Application Properties(go to Xpages tab). There you can set the Application and the session timeouts for the database. If these are blank I think they will default to server which is typically 30 minutes.
V/R,
Kev

Related

Xpages - Document refreshing with old values

I have some code, that if a user selects a "NO" answer on a certain field (Q1), it removes the answers of sub question related to Q1, and also hides them in the UI.
This works fine, and I do a partial refresh on the div containing all the questions. However, when I then click on the same question selecting answer "Yes" which then shows all the sub questions, so the user can answer them again, they still have the old values attributed.
When I remove the fields, the backend document reflects this correctly, but then when I click the question which then shows the fields again in the UI, they appear in the backend document again, with their original value. If I do a context.reloadPage() at the end of my code, everything works as expected, but this breaks other functionality and I only want a partial refresh. Any ideas? Thanks
try{
if (compositeData.onClickCode) {
compositeData.onClickCode.invoke( facesContext, null );
}
document1.save();
var fieldName:string = compositeData.fieldName;
//Blank all IFM fields if user selects no IFM *CHANGE FIELDS ARRAY TO GET FROM KEYWORD*
if (fieldName == "Q1") {
print("Yes Q1");
if(document1.getItemValueString(fieldName)=="No") {
print("NO IFMS");
var questionsIFM = ["Q1a", "Q1b", "Q1c", "Q3IFM", "Q3bIFM", "Q3cIFM", "Q3dIFM", "Q4", "Q4a" ,"Q5IFM", "Q6IFM", "Q6aIFM", "Q7IFM",
"Q7aIFM", "Q7bIFM", "Q8", "Q8a", "Q9IFM", "Q9aIFM", "Q9bIFM", "Q10IFM", "Q11IFM"];
var len = questionsIFM.length;
for (i = 0; i < len; i++) {
print("Field Name: " + questionsIFM[i]);
document1.removeItem(questionsIFM[i]);
}
document1.save();
//context.reloadPage();
}
}
var guidanceOptions:string = "";
if (compositeData.guidanceOptions) {
if(#IsMember(document1.getItemValueString(fieldName), compositeData.guidanceOptions)){
guidanceOptions = document1.getItemValueString(fieldName);
}
}
viewScope.guidance = compositeData.fieldName+guidanceOptions;
}catch(e){
openLogBean.addError(e,this.getParent());
}
Instead of changing the backend document you could update the datasource with doc.setValue('fieldName','')
Alternativly, you could change the scope of the datasource to "request", this forces the datasource to reload the backend document for every request.
EDIT:
Here is an example for updating the datasource directly (Button 'Clear') which always works and updating the component (Button 'Update').
If the button 'Reload' is clicked, changes to in the fields are "stored" in the component. The button 'Update' does a partial refresh (which hides the input field), so the value is lost.
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoDocument
var="document1"></xp:dominoDocument>
</xp:this.data>
<xp:div
id="refreshMe">
<xp:inputText
id="inputText1"
value="#{document1.foo}"></xp:inputText>
<xp:inputText
id="inputText2"
value="#{document1.bar}"
rendered="#{javascript:facesContext.isAjaxPartialRefresh() == false}">
</xp:inputText>
</xp:div>
<xp:button
value="Update"
id="buttonUpdate">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="partial"
refreshId="refreshMe">
</xp:eventHandler>
</xp:button>
<xp:button
value="Clear"
id="buttonClear">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="partial"
refreshId="refreshMe">
<xp:this.action><![CDATA[#{javascript:document1.setValue('foo', '');document1.setValue('bar', '')}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button
value="Reload"
id="buttonReload">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="complete">
</xp:eventHandler>
</xp:button>
</xp:view>
I might be late to this party, but I found a way to force a reload from the back-end document. All you have to do is change the id for the dataSource a little, by adding or removing a "0" prefix to the documentId. Something like this:
return (viewScope.idPrefix? "0":"") + param.documentId
and when you want to force a reload during a partial refresh, just set
viewScope.idPrefix= !viewScope.idPrefix;
Don't forget to set ignoreRequestParams to true.

XPages: image onCclick needs 2 clicks to do what is expected

I have a custom control that contains 2 images: add and remove from favorites.
There is some code on the onCLick event of the image, and both images use a SSJS function to see if the current document is already in the favorites or not, in the visible property of each image.
All works well, execpt that I need to click twice on the image in order to see the changes in the UI. Both onClick events are set to FullUpdate (also tried partial update with the panel that contains the images).
I could move all the favorites logic into session scope variables, but I think this should work as is. I just don't understand why I need to click twice, as if the partial refresh doesn't do anything (though it is, as I see the reload Arrow in the browser!).
Can it be that the code takes too long to execute and the refresh doesn'T get the updated info???
Here's the custom control code:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:this.resources>
<xp:script src="/AppUtils.jss" clientSide="false"></xp:script>
</xp:this.resources>
<xp:image url="/favorites-add.png" id="image1"
alt="Add to Favorites" title="Add to Favorites">
<xp:this.rendered><![CDATA[#{javascript:!isInFavorites(document1.getDocument().getUniversalID(), userBean.canonicalName);
}]]></xp:this.rendered>
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:addToFavorites(document1.getDocument().getUniversalID(),userBean.canonicalName);}]]></xp:this.action>
</xp:eventHandler>
</xp:image>
<xp:image url="/favorites-remove.png" id="image2"
alt="Remove from Favorites" title="Remove from Favorites">
<xp:this.rendered><![CDATA[#{javascript:isInFavorites(document1.getDocument().getUniversalID(),userBean.canonicalName);
}]]></xp:this.rendered>
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:removeFromFavorites(document1.getDocument().getUniversalID(),userBean.canonicalName);}]]></xp:this.action>
</xp:eventHandler>
</xp:image>
</xp:view>
And here's the SSJS:
function addToFavorites(unid, userName) {
var newDoc:NotesDocument = database.createDocument();
newDoc.appendItemValue("Form","Favorite");
newDoc.appendItemValue("UserName", userName);
newDoc.appendItemValue("DocUNID", unid);
newDoc.save();
return;
}
function removeFromFavorites(unid, userName) {
var notesView:NotesView = database.getView("(lkpFavorites)");
var keys = new java.util.Vector();
keys.addElement(userName);
keys.addElement(unid);
var coll:NotesDocumentCollection = notesView.getAllDocumentsByKey(keys, true);
if(coll.getCount()==1) {
coll.getFirstDocument().remove(true);
}
return;
}
function isInFavorites(unid, userName) {
var notesView:NotesView = database.getView("(lkpFavorites)");
var keys = new java.util.Vector();
keys.addElement(userName);
keys.addElement(unid);
var coll:NotesDocumentCollection = notesView.getAllDocumentsByKey(keys, true);
if(coll.getCount()>0) {
return true;
} else {
return false;
}
}
I'd suggest you to put an xp:link around your image to cast the event code instead of using the evennts of the image directly.
OK, not sure what happened there but I manually edited the custom control's source to see wheter I had empty eventHandler as suggested by Oliver, and it started to work as expected. I am totally unsure of what I changed: to my knowledge, all I did was to add extra "returns" in the source view, to make it more readable... Christmas gift I guess.
All is good now. Thanks to all :)

How to perform multiple page updates behind a single button in XPages

This is a high level question but does have specific answers.
I have a requirement where I need to perform an action two times, and update the user with a message before trying the action a second time. I also want to update the user prior to the first action.
Here is the timeline/sequence of events:
User presses button
Display message "operation starting"
Perform operation
If successful, show "operation successful", if operation fails
show "operation failed - retrying"
Retry Operation
If successful, show "operation successful", if operation fails show "please try again later".
When I coded this in my java method, the only thing that displayed was the final message. I tried using Thread.sleep(1500); to give the message a chance to display, but ONLY the final message will ever be displayed.
I then tried using SSJS to accomplish this task, but the result is the same. I think I understand why this is happening.
My question is: Is it even possible to do multiple partial refreshes like this. What is the best approach that I can take to accomplish this requirement. What workarounds or hacks can anyone think of.
If you are wanting to just try twice, you could create an rpc control that does the functionality you want, then call it with a call back
var deferred = service.doSomethingCool();
deferred.addCallback(function(data) {
if (data.status == 'error') {
//set UI Label Fail
var insideDeferred = service.doSomethingCool();
insideDeferred.addCallback(function(data) {
if (data.status == 'error') {
//set UI Label Fail
}
else {
//set UI Label Success
}
}
}
}
This should work for you assuming you have an RPC control named service and method called "doSomethingCool"
I tried Mark's post for a progress bar once. http://linqed.eu/?p=174 Didn't get it to work but didn't go deep into the effort. The solution is probably in there.
What you want should be doable of course. I would think at the least you use CSJS to do the heavy lifting really. Have CSJS call SSJS probably via RPC or XAgent and that does all the work of first and secondary message.
I'm just light on the actual details of making that work. :)
Yes, it's possible. We can do back and forth client side and server side operations n number of times in a single button click.
Create a button with CSJS code for alert.
Write SSJS code for your operation.
Now the trick is depends on whether your operation is partial or complete refresh.
If partial refresh, use oncomplete / onfailure event in eventhandler to write CSJS code to perform button click operation. Use a hidden input field to store number of retry and to determine at what count the retry has to stop.
If full refresh, oncomplete event does not triggered. Write your CSJS code on clientload event. In this case, Create a hidden input field and bind it to a view scope variable. Use it to store the success or failure in SSJS code and retrieve the value in CSJS code to check and retry.
I have included a sample code with buttons however it can be implemented in many different ways.
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="label1">
<xp:this.script><![CDATA[alert("operation starting");]]></xp:this.script>
<xp:this.action><![CDATA[#{javascript:viewScope.status = "first operation completed";
print(getComponent("fail").getValue());}]]></xp:this.action>
<xp:this.onComplete><![CDATA[alert("first operation completed. starting second");
document.getElementById("#{id:ihRetry}").value = "False";
document.getElementById("#{id:button2}").click();]]></xp:this.onComplete>
<xp:this.onError><![CDATA[if ( document.getElementById("#{id:ihRetry}").value == "False" ) {
alert("first operation failed. retry again");
document.getElementById("#{id:ihRetry}").value = "True";
document.getElementById("#{id:button1}").click();
} else {
alert("first operation failed again. starting second");
document.getElementById("#{id:ihRetry}").value = "False";
document.getElementById("#{id:button2}").click();
}]]></xp:this.onError>
</xp:eventHandler>
</xp:button>
<xp:button value="Label" id="button2" style="display:none">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="label1">
<xp:this.action><![CDATA[#{javascript:viewScope.status = "second operation completed";}]]></xp:this.action>
<xp:this.onComplete><![CDATA[alert("second operation completed. starting third");
document.getElementById("#{id:ihRetry}").value = "False";
document.getElementById("#{id:button3}").click();]]></xp:this.onComplete>
<xp:this.onError><![CDATA[if ( document.getElementById("#{id:ihRetry}").value == "False" ) {
alert("second operation failed. retry again");
document.getElementById("#{id:ihRetry}").value = "True";
document.getElementById("#{id:button2}").click();
} else {
alert("second operation failed again. starting third");
document.getElementById("#{id:ihRetry}").value = "False";
document.getElementById("#{id:button3}").click();
}]]></xp:this.onError>
</xp:eventHandler>
</xp:button>
<xp:button value="Label" id="button3" style="display:none">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="label1">
<xp:this.action><![CDATA[#{javascript:viewScope.status = "third operation completed";}]]></xp:this.action>
<xp:this.onComplete><![CDATA[alert("third operation completed.");
document.getElementById("#{id:ihRetry}").value = "False";]]></xp:this.onComplete>
<xp:this.onError><![CDATA[if ( document.getElementById("#{id:ihRetry}").value == "False" ) {
alert("third operation failed. retry again");
document.getElementById("#{id:ihRetry}").value = "True";
document.getElementById("#{id:button3}").click();
} else {
alert("third operation failed again. end");
document.getElementById("#{id:ihRetry}").value = "False";
}]]></xp:this.onError>
</xp:eventHandler>
</xp:button>
<xp:inputHidden id="ihRetry">
<xp:this.value><![CDATA["False"]]></xp:this.value>
</xp:inputHidden>
<xp:label value="#{viewScope.status}" id="label1"></xp:label>
</xp:view>

Using JQuery to mask input fields. When I refresh a panel that contains those fields the masking stops working

I have several phone number fields that use jquery masking to format the input. See the code below. The fields work great until a combo box change above refreshes a panel that contains those fields. Once the refresh happens my masking stops working.
Any idea why and how to prevent this from happening?
<xp:scriptBlock id="scriptBlock7">
<xp:this.value><![CDATA[
jQuery(function($){
x$("#{id:dayPhone1}").mask("(999) 999-9999? x 9999999", {placeholder : " " } );
x$("#{id:eveningPhone1}").mask("(999) 999-9999? x 9999999", {placeholder : " " } );
x$("#{id:cellular1}").mask("(999) 999-9999? x 9999999", {placeholder : " " } );
});
]]></xp:this.value>
</xp:scriptBlock>
The jQuery is only run one time. It manipulates the DOM to give the mask effect. Once you run a partial refresh the original DOM is returned to the user and the mask is no longer in effect.
When the partial refresh happens the jQuery code does not know to apply itself back to the mask again. You have a number of choices, but the best is probably:
In the onComplete event of the partial refresh you can call the mask code again to reapply the "Mask". What I don't know is if the mask code will reset the fields or honor the values therein. I that is the case then take a look at the plugin code and see what options you have.
<xp:button value="Label" id="button1" styleClass="startLoginProcess" style="display:none">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="somethingHere"
onComplete="applyMaskCodeAgainHere">
</xp:eventHandler>
</xp:button>
To improve the code above because it looks like you are applying the same mask I suggest using a class selector and simplifying your code to look more like this:
<xp:scriptBlock id="scriptBlock7">
<xp:this.value><![CDATA[
jQuery(function($){
$('.phoneMask').mask("(999) 999-9999? x 9999999", {placeholder : " " } );
});
]]></xp:this.value>
</xp:scriptBlock>
put a styleClass="phoneMask" on your field :)
Is your scriptBlock also on the panel that is being refreshed? It needs to be in order for the the mask to be reapplied to the fields after the refresh.
You can remove the mask and reset it...
$(`#${id:dayPhone1}`).val(newPhoneValue).unmask().mask('(00) 00000-0000', {clearIfNotMatch: true});
This worked for me and should solve your problem!
TLDR: .unmask() before .mask()

xpages validation on field having onChange script

There is a required field:
<xp:this.validators>
<xp:validateRequired
message="Required field. Please add some text.">
</xp:validateRequired>
</xp:this.validators>
Also, the value from this field is copied ( using the onChange event ) to other fields:
<xp:eventHandler event="onchange" submit="true"refreshMode="norefresh">
<xp:this.action><![CDATA[#{javascript:Cdoc.setValue("dlg_Localitate",Cdoc.getValue("txt_LocalitateCompanie"));
Cdoc.setValue("dlg_Localitate_1",Cdoc.getValue("txt_LocalitateCompanie"))}]]>
</xp:this.action>
</xp:eventHandler>
An inconvenient issue appears when I just click the field to fill it: the validation message appears. Is because the field initially is empty and the code I added is into the onChange event?
I'd like to use this field as required before users can save the doc.
I tried set the values by CSJS, but without a result...
var string = XSP.getElementById("#{id:inputText1}").value
XSP.getElementById("#{id:txt_LocalitateS}").value = string
XSP.getElementById("#{id:txt_LocalitateP}").value = string
Also, let say I enter a value for inputText1 and later on I enter a new value... How can I update automatically the other 2 fields with the new value?
I tried something like this:
<xp:inputText id="inputText1" value="#{Cdoc.txt_LocalitateCompanie}"
style="height:20.0px;width:122.0px;font-weight:bold;font-size:10pt;font-family:verdana"
required="true">
<xp:this.validators>
<xp:validateRequired message="Completarea localitatii este obligatorie.">
</xp:validateRequired>
</xp:this.validators>
<xp:typeAhead mode="full" minChars="1" ignoreCase="true"
id="typeAhead1">
<xp:this.valueList><![CDATA[#{javascript:#DbLookup(#DbName(),"vwLocalitati",Cdoc.txt_LocalitateCompanie,1,"[PARTIALMATCH]");}]]></xp:this.valueList>
</xp:typeAhead>
<xp:eventHandler event="onchange" submit="true"
refreshMode="norefresh">
<xp:this.action><![CDATA[#{javascript:Cdoc.setValue("dlg_Localitate",Cdoc.getValue("txt_LocalitateCompanie"));
Cdoc.setValue("dlg_Localitate_1",Cdoc.getValue("txt_LocalitateCompanie"))}]]></xp:this.action>
<xp:this.script><![CDATA[XSP.partialRefreshGet("#{id:txt_LocalitateS}", {
onComplete: function() {
XSP.partialRefreshGet("#{id:txt_LocalitateP}", {
onComplete: function(){ }
});
}
});]]></xp:this.script>
</xp:eventHandler>
</xp:inputText>
Thanks in advance
Two things here. First, you should disable validators for onChange event, therefore it won't display the validation error.
Second, when you use a CSJS script together with a SSJS, it will fire the CSJS one and if it returns true, proceed with the SSJS. So if you want your CSJS code run after SSJS, you can place it into oncomplete.
If I understood your question correctly, the following code would solve it.
<xp:inputText
id="inputText1"
value="#{Cdoc.txt_LocalitateCompanie}"
style="height:20.0px;width:122.0px;font-weight:bold;font-size:10pt;font-family:verdana"
required="true">
<xp:this.validators>
<xp:validateRequired
message="Completarea localitatii este obligatorie.">
</xp:validateRequired>
</xp:this.validators>
<xp:typeAhead
mode="full"
minChars="1"
ignoreCase="true"
id="typeAhead1">
<xp:this.valueList><![CDATA[#{javascript:#DbLookup(#DbName(),"vwLocalitati",Cdoc.txt_LocalitateCompanie,1,"[PARTIALMATCH]");}]]></xp:this.valueList>
</xp:typeAhead>
<xp:eventHandler
event="onchange"
submit="true"
refreshMode="norefresh"
disableValidators="true">
<xp:this.action><![CDATA[#{javascript:Cdoc.setValue("dlg_Localitate",Cdoc.getValue("txt_LocalitateCompanie"));
Cdoc.setValue("dlg_Localitate_1",Cdoc.getValue("txt_LocalitateCompanie"))}]]></xp:this.action>
<xp:this.onComplete><![CDATA[if(dojo.byId("#{id:txt_LocalitateP}")) {
XSP.partialRefreshGet("#{id:txt_LocalitateP}", {
onComplete: function() {
XSP.partialRefreshGet("#{id:txt_LocalitateS}", {
onComplete: function(){ }
});
}
});
}]]></xp:this.onComplete>
</xp:eventHandler>
</xp:inputText>
UPDATE: In your case, the field you want to refresh is on the second tab with partialRefresh="true". It means that at the time of partialRefreshGet, the target fields might not exist in the DOM. I have added a check now.
this is taken from my comments and put into an answer:
onChange events are generally frowned upon due to performance and user experience. If, however, the field is a listed control ie combobox it is not so dramatic. The following options/ideas are available
Take out the onChange() to test whether that makes a difference. If so, move your code.
Use an update button to change all the fields en masse also preventing information that is already inputted from being deleted unwanted-ly
create your own validation method and show/hide a label manually (hack-y)
Research how to manually put text into an errors control
If the field is in a dialog box, move the onChange() to the open/close methods of the dialog
FURTHER EDIT
An idea that I might suggest is using the xspDoc.getDocument(true) method to push all changes from the xpage to the background document. Something tells me that this might make a difference with the server reading the changes to the document and realizing that it is not empty.
ADDITIONAL IDEAS
I did not mention this because it is a bit more advanced, but should also get the job done assuming the refreshes are done. Even that is not that big of a deal. You could read all of your data from the document into a java bean. This bean is then the "data source" for your page and you bind all of your controls to the properties of this bean. You will then use EL to bind your controls to the bean. In the setters for those variables that trigger changes in other fields, change those values. So,
public PageBean(){
//read connection information out of the URL and get the correct information out of the document
//set all variables
firstName=doc.getItemValueString("firstName");
}
private String firstName;
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName = firstName;
setLastName("Schmidt");
}
....
Once you register your bean with faces-config.xml, you can then use EL to access the data
#{PageBean.firstName}
#{PageBean.lastName}
Then you can get your document again in save and reset the values, save and release.

Resources