GXT custom event handler code executes multiple times - gxt

I have implemented MVP pattern in my GXT project. The system registers customers as part of it function. Also the system user can search for the registered user providing the id.
i have added an OnClick event to the "search customer" button.
/* On click search button */
view.getBtnSearch().addListener(Events.OnClick, new Listener<BaseEvent>() {
#Override
public void handleEvent(BaseEvent be) {
eventBus.fireEvent(new CustomerRegistrationTabSelectionEvent(0, false));
eventBus.fireEvent(new CustomerFetchEvent(view.getValueCustSearchParameter(), view.getValueCustSearchValue(), true));
}
});
The CustomerRegistrationTabSelectionEvent does select the relevant tab and enables other tabs. Thats all it does.
Here is the handler for the custom event CustomerFetchEvent.
eventBus.addHandler(CustomerFetchEvent.TYPE, new CustomerFetchEventHandler() {
#Override
public void fetchCustomer(CustomerFetchEvent event) {
searchCustomer(event.getParameter(), event.getParameterValue(), event.isOpenFirstTab());
}
});
The issue is the search customer method is executed multiple times and if there is a invalid search the error message dialog shows multiple popups. Within the searchCustomer method i call for service which fetch me the customer data or show the popup error message if the search is invalid.
im using GXT 2.2.5 and JRE 1.6.
Could anyone help me in finding out why the code is executed multiple times?
Added Later:
When i run the application first time the code is only executed only once, therefore only 1 popup. Then i logout of the system and log in again (navigating to the same page where the "search customer" button exists.) and the code is executed twice. Likewise equal to the number of times i create/navigate to the particular page, the code executes. Is it actually adding the event handler code without removing the last one every time i recreate the page?

Yes, it seems that 'addHandler' adds handler multiple times, but stores previous context. Your code should add handlers only once, on initialization phase. You can check the number of handlers with 'getHandlerCount' method.

Ya. I fixed it!Here is the solution Unbinding presenters necessary in GWT
U can read more here. http://draconianoverlord.com/2010/11/23/gwt-handlers.html
what happened actually was, the presenter objects where i have registered with HandlerManager to receive events were not garbage collected. Because though i remove the reference to the presenters still the HandlerManager holds a reference to those objects. So every time i kept on creating new presenters on top of the old presenters of the same class. so a event is listened by multiple objects of the same class. so u need to ensure that the unused presenters are garbage collected by removing the registered handlers
in HandlerManager.

Related

SSJS onClick action will not fire on XPage

I found this question, but it does not appear to be resolved, and I also have more to add.
First off, the linked question defines pretty much the same issue that I am having.
1. I am using the application layout control from the ExtLib
2. It does not matter if the button is in that control or not.
3. CSJS actions will fire from the button, SSJS actions will not fire.
4. No errors are present
5. Browser / cache is irrelevant as the server side action just will not fire.
After seeing the linked question, I looked in the Local file in the package view and found an anomaly that makes me wonder if it could be the cause. I have never seen such a file before and even looked in my other xpage projects just to be sure.
This file cannot be deleted, and when clicked upon, the display window says that the element does not exist.
Does anyone know what this file is, how I can remove it, or could it be that my application is corrupted?
**More Info **
The following snippet is copied from the java file for the XPage located in the Local directory. Everything looks fine to me.
private UIComponent createEventHandler(FacesContext context,
UIComponent parent, PageExpressionEvaluator evaluator) {
XspEventHandler result = new XspEventHandler();
String sourceId = "button2/xp:eventHandler[1]/xp:this.action[1]/text()";
MethodBinding action = evaluator.createMethodBinding(result,
"#{javascript:view.postScript(\"alert(\'server script fired!\')\");}",
null,null, sourceId);
result.setAction(action);
result.setSubmit(true);
result.setEvent("onclick");
result.setRefreshMode("complete");
return result;
}
EDIT
Moving all of the design elements into a new .nsf so that file is no longer present does not change the problem of the SSJS onclick action not firing. That strange file is however not present.
Is it failing on a converter / validator? That can cause it to skip out of the lifecycle before Invoke Application phase. To test whether a button is actually working, you can also use "Do not validate or update data". Then the SSJS runs in Apply Request Values phase. If the SSJS is triggered (you won't have the latest data from the browser in the data model or components though), then it's another good bet for converter or validator failure.

How to refresh other users Vaadin Table without causing Concurrent Modification Exception?

Use Case: User logged in and a Vaadin Table component opened showing statuses of appointments. Every row has a drop down (ComboBox) to change status (Scheduled, Arrived, Reviewed). Now multiple users has opened this table in their own browsers and making continuous changes to appointment status. These changes should be reflected on all opened tables i.e if user A changes status of appointment appt-1 it reflects and refresh on all Tables currently opened.
Previously we applied event based refreshing with ICE-PUSH Add-on i.e if Change made on PC-1 (i.e Application instance a1), i get the other instances of Vaadin application from static CopyOnWriteArrayList from MainApplication class and by that instance I call loadTable function. after that I call the ICEPUSH to push new changes to all users.
public class MainApplication extends Application {
public static CopyOnWriteArrayList<MainMedMaxApplication> appList=new CopyOnWriteArrayList<MainMedMaxApplication>();
#Override
public void init() {
setMainWindow(new Window("APPointment Dashboard"));
getMainWindow().setContent(mainLayout);
setMainComponent(getCustomTable());
//Custome Table make table . it also register listeners over table.
//loadTable will load the table.
loadTable()
appList.add(this);
}
}
public void loadTabl(String date) {
//this will reload the table component By Querying database
}
private void registerlistener() {
table.addListeners()
{
//do any change to table in this instance and save it to db then call ICE push so it can referesh all app instances by getting from applist.
synchronizePortlets();
}
}
public void synchronizePortlets() {
// TODO Auto-generated method stub
Iterator<MainApplication>itM = appList.iterator();
while(itM.hasNext()) {
MainApplication app = itM.next();
app.loadTabl();
app.getPusher().push();
}
}
}
This works fine but in some conditions when to many frequent changes made then Concurrent Modification Exception rises. so if any one can help to improve this?
The solution I am thinking after this is to refresh table component not forcefully rather continuously in every 1 mint by its own app instances. This will query database and reload the table container with updated statuses. For this purpose I use Refresher add-on But it raises an exception i.e ConcurrentModificationException, because sometimes user also changing the table component by changing combo statuses in table meanwhile refresher refresh the Table and here raises concurrent Modification exception. So I am thinking of freezing Table component from user point of view so user can't do anything and in background can easily refresh table.
If for this use case you guys have better solution please do tell me. I am grateful of you.
Using Vaadin 6.8.12, java 1.7, apache Tomcat 7.42
Vaadin 6
You need to apply synchronization since you're making changes to the GUI from another thread (and I think it doesn't matter whether Refresher or IcePush is used, I think in both cases you'll use another thread). Synchronize on the Application instance.
See this post on the Vaadin forum.
Vaadin 7
EDIT: I encourage you to upgrade to Vaadin 7.1 and use this new method on UI: UI#access as is recommended here.

Is there a paint or update method (rendering loop) in JavaFX2 so that I can update the UI in a loop?

In Swing you have paint or update(Graphics g) method for each UI component which executes every frame. You can put your drawing logic in the overrided method and draw whatever you want. What is the paint method for JavaFX2 UI?
What I want to do is my UI receives control information from a socket server (another thread). Whenever a control information is received, I should update the UI.
There are two problems:
1. The control information is received from a different thread, it can not access the rendering thread directly.
2. How to update the UI constantly?
For Q1, I have a solution if I know where the update function is (Q2).
I can declare a List object, and insert the new control command received from the socket into the list. In the rendering loop, I can just observe the List object, retrieve the unprocessed command, and delete the already processed command.
However, where can I find such a rendering loop function? I guess maybe I can also do it with javax.concurrent.Task, but I don't find a way to do it.
I think i find the method, I use the following method and it can work. I don't know if there is a better solution
final Duration oneFrameAmt = Duration.millis(1000/10);
final KeyFrame oneFrame = new KeyFrame(oneFrameAmt,new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
//put UI update here
}
});
TimelineBuilder.create().cycleCount(Animation.INDEFINITE)
.keyFrames(oneFrame)
.build()
.play();

How to handle LWUIT dialogs shown on background threads

I have written an application in LWUIT targeted for a J2ME phone (Sprint DuraXT). The application is for pickup and delivery van drivers. It receives dispatches from a back-end dispatching system that describe pickups and delivers the driver must make. As the drivers, execute the pickups and deliveries, the driver enters status information that is sent back to the dispatching system.
Now, during the processing of a pickup or delivery, the driver may be presented with error dialogs (incorrect field entry), yes/no confirmation dialogs (confirming some action) and information dialogs (indicating some status the driver should be aware of).
In addition, there is a background thread listening for dispatches coming from the back-end server. In the current implementation, this background thread can also create yes/no confirmation dialogs and information dialogs. These dialogs are more like an alert as they have an associated sound, but they are simply dialogs.
As long as these two dialogs do not occur “simultaneously” every thing works as expected. You can dismiss the dialogs and the app proceeds as expected.
However, when you are on a screen and there is a dialog already showing and a second one from the background thread occurs, you sometime wind up with the wrong screen showing and it is “frozen”. E.g. the soft keys have no effect.
My hypothesis is that there is a race condition between the threads that are dismissing the dialogs. It goes like this. The EDT is blocked showing the dialog that arises as part of the form’s logic. The background thread is also blocked showing a dialog. Now when the dialog showing on the EDT is dismissed, the form is restored, but the EDT may go off and display another form (via show()). When the dialog displayed by the background thread is dismissed, the form which was showing when the dialog was initially displayed is sometimes restored. Now, the display shows a different form than the one the EDT might have shown.
It is pretty clear that this problem is caused by the dialogs resulting from the activities of the background thread. So the basic question is: “How to handle the dialogs arising from the background thread?” I have some thoughts but none yield a particularly clean implementation. I am hoping somebody has had to deal with this same problem and has a suggestion.
I have tried synchronizing the dialog construction and display so that only one dialog can get displayed at a time. This certainly improves the UI, but does not fully resolve the problem. The race begins when the first dialog is dismissed. Here are some other ideas,
If a dialog is shown by a thread other than the EDT, call show on the form at the top of the display stack when the dialog is dismissed. This is a bit of a hack, but may be a workaround.
Run dialogs to be shown by the background thread on the EDT. There are several ways to do this, but the question is will it resolve the problem? Will using an EventDispatcher help? I have experimented using an EventDispatcher to fire an ActionEvent containing a subclass of a Dialog as a source. The subclass contains a show() method which invokes the correct form of the Dialog show method. The class holding the EventDispatcher (global to the application) listens for these events. When the event arrives, the show method is invoked. For information dialogs that simply continue execution from wherever they are dismissed, this should work. For yes/no dialogs, you may have to create something like yes/no callbacks to handle the bifurcation in the logic. And what is not obvious is if this will actually serialize the processing of the dialogs on the EDT thread. This seems complicated.
Any ideas?
I actually hit upon the solution after a bit of experimentation. Because the Dialogs are part of a more compilcated action involving yes/no Dialogs and database queries, I found I had to wrap the whole action in a class which implements the Runnable interface. Then I run the action via Display.getInstance().callSeriallyAndWait(runnable).
So others may benefit from this discussion, here is a example of one of these classes with the action embedded in the run method.
private class CancelOrder implements Runnable {
private KWMap order;
public CancelOrder(KWMap order) {
this.order = order;
}
public void run() {
String orderNum = getString(order, OrderTable.ORDER_NUM);
if (legStatusTable.isOrderStarted(orderNum)
&& !orderTable.isOrderComplete(order)) {
String msg = "You received a cancellation message for Order "
+ orderNum
+ " which has been started but is not finished."
+ "\nDo you want to keep it?";
if (app.yesNoDialog(msg, "Yes", "no")) {
sendCancelResponse(order, "Yes", "");
} else {
deleteOrder(orderNum);
sendCancelResponse(order, "No", "");
}
} else {
// order has neither been started nor completed.
deleteOrder(orderNum);
sendCancelResponse(order, "Yes", "");
app.alertDialog("Dispatcher cancelled Order " + orderNum);
}
}
}
The key thing here is that the action contains logic depending on how a user responds to a yes/no Dialog and there are operations on an underlying database and messaging subsystem as well. Except for the Dialogs, nothing in this action blocks the EDT for more than a few 100s of milliseconds, so the application runs very smoothly. The app coorectly handles dislogs stacking on top of each other which was a problem with the simple apporach of letting these actions run on the background (non EDT) thread.

XPages sometimes refresh and lose content

I hope someone can help me solve a very serious problem we face at the moment with a business critical application losing data when a user works in it.
This happens randomly - I have never reproduced this but the users are in the system a lot more than me.
A document is created with a load of fields on it, and there are 2 rich text fields. We're using Domino 8.5.3 - there are no extension lib controls in use. The document has workflow built in, and all validation is done by a SSJS function called from the data query save event. There is an insane amount of logging to the sessionscope.log and also this is (now) captured for each user in a notes document so I can review what they are doing.
Sometimes, a user gets to a workflow step where they have to fill in a Rich Text field and make a choice in a dropdown field, then they submit the document with a workflow button. When the workflow button is pressed (does a Full Update) some client side JS runs first
// Process any autogenerated submit listeners
if( XSP._processListeners ){ // Not sure if this is valid in all versions of XPages
XSP._processListeners( XSP.querySubmitListeners, document.forms[0].id );
}
(I added this to try and prevent the RTF fields losing their values after reading a blog but so far it's not working)
then the Server-side event runs and calls view.save() to trigger QS code (for validation) and PS code to run the workflow agent on the server.
95% of the time, this works fine.
5% of the time however, the page refreshes all the changes made, both to the RFT field (CKEditor) and the dropdown field are reloaded as they were previously, with no content. It's like the save hasn't happened, and the Full Update button has decided to work like a page refresh instead of a submit.
Under normal circumstances, the log shows that when a workflow button is pressed, the QuerySave code starts and returns True. Then the ID of the workflow button pressed is logged (so I can see which ones are being used when I am reviewing problems), then the PostSave code starts and finally returns true.
When there is a problem, The QuerySave event runs, returns true if the validation has passed, or false if it's failed, and then it stops. The ID of the workflow button is also logged. But the code should continue by calling the PostSave function if the QuerySave returns true - it doesn't even log that it's starting the PostSave function.
And to make matters worse, after the failure to call the PostSave code, the next thing that is logged is the beforePageLoad event running and this apparently reloads the page, which hasn't got the recent edits on it, and so the users loses all the information they have typed!
This has to be the most annoying problem I've ever encountered with XPages as I can find no reason why a successful QuerySave (or even a failure because mandatory fields weren't filled in) would cause the page to refresh like this and lose the content. Please please can someone help point me in the right direction??
It sounds as if in the 5% use cases, the document open for > 30mins and the XSP session is timing out - the submit causes the component tree to be re-created, and the now empty page returned back to the user. Try increasing the time out for the application to see if the issue goes away.
I would design the flow slightly different. In JSF/XPages validation belongs into validators, not into a QuerySave event. Also I'd rather use a submit for the buttons, so you don't need to trigger a view.save() in code. This does not interfere with JSF's sequence of things - but that's style not necessarily source of your problem.... idea about that:
As Jeremy I would as a first stop suspect a timeout, then the next stop is a fatal issue in your QuerySave event, that derails the runtime (for whatever reason). You can try something like this:
var qsResult = false;
// your code goes here, no return statements
// please and if you are happy
qsResult = true;
return qsResult;
The pessimistic approach would eventually tell you if something is wrong. Also: if there is an abort and your querySave just returns, then you might run in this trap
function noReturn() {return; } //nothing comes back!
noReturn() == true; --> false
noReturn() == false; --> false
noReturn() != false; --> true!!!!
What you need to check: what is your performance setting: serialize to disk, keep in memory or keep latest in memory? It could be you running foul of the way JavaScript libraries work.
A SSJS library is loaded whenever it is needed. Variables inside are initialized. A library is unloaded when memory conditions require it and all related variables are discarded. so if you rely on any variable in a JS Function that sits inside a SSJS library between calls you might or might not get the value back, which could describe your error condition. Stuff you want to keep should go into a scope (viewScope seems right here).
To make it a little more trickier:
When you use closures and first class functions these functions have access to the variables from the parent function, unless the library had been unloaded. Also functions (you could park them in a scope too) don't serialize (open flaw) so you need to be careful when putting them into a scope.
If your stuff is really complex you might be better off with a backing bean.
Did that help?
To create a managed bean (or more) check Per's article. Your validator would sit in a application bean:
<faces-config>
<managed-bean>
<managed-bean-name>workflowvalidator</managed-bean-name>
<managed-bean-class>com.company.WfValidator</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
</faces-config>
Inside you would use a map for the error messages
public Map<String,String> getErrorMessages() {
if (this.errorStrings == null) { // errorStrings implements the MAP interface
this.loadErrorDefinitions(); //Private method, loads from Domino
}
return this.errorStrings;
}
then you can use EL in the Error message string of your validators:
workflowvalidator.errorMessage("some-id");
this allows XPages to pick the right one directly in EL, which is faster than SSJS. You could then go and implement your own custom Java validator that talks to that bean (this would allow you bypass SSJS here). Other than the example I wouldn't put the notes code in it, but talk to your WfValidator class. To do that you need to get a handle to it in Java:
private WfValidator getValidatorBean() {
FacesContext fc = FacesContext.getCurrentInstance();
return (WfValidator) fc.getApplication()
.getVariableResolver()
.resolveVariable(fc, "workflowvalidator");
}
Using the resolver you get access to the loaded bean. Hope that helps!
My experience is that this problem is due to keeping page in memory. Sometimes for some reason the page gets wiped out of memory. I'm seeing this when there is a lot of partial refreshes with rather complex backend Java processing. This processing somehow seems to take the space from memory that is used by the XPage.
The problem might have been fixed in later releases but I'm seeing it at least in 8.5.2.
In your case I would figure out some other workaround for the CKEditor bug and use "Keep pages on disk" option. Or if you can upgrade to 9.0.1 it might fix both problems.

Resources