I've created an XAgent to export Notes data to Excel along the lines of the following:
http://www.dominoguru.com/pages/developer2010_xpagexlsexport.html
http://xpageswiki.com/web/youatnotes/wiki-xpages.nsf/dx/How_to_export_to_Excel_or_other_formats
The agent works fine the first time I run it in the Notes client. However, the second time I trigger the XAgent, I get the Location chooser letting me determine where to save the file, but nothing is ever downloaded. Worst of all, my Notes client locks up. I need to completely reboot my PC to get the XAgent to work again. I'm using Notes 8.5.3
When I run the agent within IE, it works fine every time.
Has anyone else experienced this behavior when exporting data via an XAgent running in XPiNC?
I wouldn't recommend to use file emitting XAgents in XPiNC. You do have access to the file system after all. So it is easier to directly write to a file and then just display the link. If you follow my XAgent advise all your worker code would be in a class which you pass the Stream object, so you only have slightly different wrapper code around it.
So you would (pseudo-code)
OutputStream out;
if(runningInXPiNC()) {
out = new FileOutputStream(new File(determineLocalFileName()));
} else {
out = getOutputStreamFromContextandResponseObject();
}
renderThatExelFile(out);
The rendered property of the page would be true for XPiNC, so you can display "Open the file" URL that points to "file://"+determineLocalFileName()
Related
I'm using Notes/Domino 8.5.3. I've added a button control to an xpage. The button uses a Confirm Action to display a client-side prompt to the user before continuing with the next action defined for the button. When I use static text for the Confirmation Text for the Confirm Action, the confirmation prompt is displayed. However, when I change the Confirmation Text to be computed, and retrieve the text from a profile document, the confirmation prompt it not displayed at all in XPiNC. The confirmation prompt with the computed confirmation text is displayed just fine in a browser. Is there a work-around for this issue with XPiNC?
Following is the code I'm using in the Confirm Action to get the text for the prompt:
var server = database.getServer();
var dbProfile:NotesDocument = database.getProfileDocument("DBProfile", "");
var msg = dbProfile.getItemValueString("ContactsInitUpdatePrompt");
return msg;
To further my comments, this is a work around I use the below code for an app that uses the bootstrap extension library on the web but uses basic functionality with xpinc.
If the values for xPinc are different you could make the confirm action different in the browser and in the client.
if (#ClientType()== "Notes")
{
<action>;
}
else{
<action>;
}
I think that profile documents are a bad idea in xPages though. Having to restart HTTP to get a new value ruins the point I think. Almost better to hard code values at that point. I think you can set application scope to handle the work of profile documents. But then application scope in xpinc is just on the current machine as the server is the client.
I'm writing a chrome extension and have a question.
My extension has some .html page in it, let it be 'popup.html'. I inject a content script into some page and this script opens a 'popup.html' in a new tab with something like 'var p = window.open(chrome.extension.getURL('/popup.html'), "popup")', which works perfectly. Next, I need to pass some data to this window and I can't figure how to do it in a simple way.
For some reason I can't call child window's function from a content script with
var p = window.open(chrome.extension.getURL('/popup.html'), "popup");
p.foo(data);
In the console I see Uncaught TypeError: Cannot call method 'foo' of undefined message.
I can't pass data in a query string, because the data is simply too big.
Is there an elegant and simple way to pass data to such kind of window? I thought about messaging, but how do I effectively get tab ID of a newly opened window w/out using a background page?
Thanks a lot in advance.
UPD:
I tried to inverse the logic and get a data from parent window with 'window.opener.foo()' but in a newly opened tab window.opener returns null.
Ok, I found two solutions to my problem.
1) Add a background page, which opens a popup with chrome.tabs.create(). Then send a message from a content script to a background page, which re-sends it to a corresponding tab via chrome.tabs.sendMessage(). It looks a little ugly, but works.
2) A better one, w/out background page. Extension (popup) page creates a listener for long-lived connection. Then content script sends a message to this connection. A problem here is that a listener is not created right after the page is opened, so there should be a mechanism for a content script to wait until popup is loaded. It can be a simple setTimeout or a notification from popup via same long-lived connection.
If anyone has a better solution I'd gladly check it out as well.
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.
I am currently have this message handler line:
MESSAGE_HANDLER(`WM_SETREDRAW`, onSetRedraw)
I would like to know, is there any window message (eg: WM_???) that is connected/related to 'when a website has finish loading inside IE' ?
So I can use it to replace the above WM_SETREDRAW. I want to do something like, when the IE finish loaded a website, it call onSetRedraw.
If no one answers, go Gogoling for an application "spy" tool, which will tell you which messages your program receives. Make a one line app which one launches the browser and spy on that.
Alternatively, what API are you using to launch the browser? Look at it's return value.
Btw, I strongly suspect that you will only get a message when the browser is launched, not every time it loads a new page (or even the first page).
You may not be able to do what you want very easily. A possibility might be to search for the window by title bar, get it's handle, walk its control list until you get to the status bar and check its text in a loop until it is done.
A further possibility, if this is only for yourself, woudl be to get an open source browser which uses the MSIE rendering engine and make a one line change at "the right place in the code" to send a message to your app every time a new page is loaded.
I've written a Blackberry appliation with the Blackberry JDE, running on a 9000 simulator. I tested it a week or so ago and loaded it on a Blackberry 9000 phone, and everything worked just fine. Sometime between then and now, though, something went wrong.
My code does the whole moving arrow "loading things from the internet" or whatever thing, but no screens pop up. My original screen, which is just a MainScreen with a RichTextField doesn't load at all. This screen, at least, has most likely not changed in the passing week, so if something broke, it would be in one of the later screens/lines of code that it shouldn't even be getting to yet!
Is it possible that my .jad or .cod file are corrupted somehow? I noticed that when I first put code on my machine, I just stuck in the .cod file that Eclipse provided me. Then, last week, the .cod file it gave me didn't work, because it was ACTUALLY a zip file with a two .cod files inside of it. Using the .cod file with the same name as the .cod file they were in succesfully loaded my app. I did the same this time, and I don't get invalid cod file errors or anything, but the app is still as broken.
Is there some direction I should be looking? Is the issue likely to be in my code, the cod file, the phone, or somewhere completely else?
-Jenny
Edit: I've narrowed it down to the problem only occuring if I attempt to load a particular screen. My problem is that this screen is nearly identical to another screen that IS working just fine on the actual device. Both screens are generated from the same method (which makes a webservice call and gets XML back and parses it to populate the fields of the screen). The only difference is that the screen that is breaking is going to a different URL. This URL DOES work (both from a browser and from the simulated device), so I"m at a loss. The application doesn't seem to crash, (it's still running in the background), it just doesn't attempt to display anymore.
Edit:
Okay, I'm seeing some tunneling errors immediately after I load my app, (but before I execute any of my networking code). When i do execute my networking code, it works just fine, unless it happens to be for my "Rental" section. I commented out all calls to that, and made my menu item for Rentals simply make a print statement. The code behaves identically (it freezes, or displays a white screen after selecting the button). All other menu items work (including those that call threads or network methods). And the rentals menu sucessfully executes in the simulator.
private MenuItem _rentals = new MenuItem("My Rentals", 110,
10) {
public void run() {
//if the last thing I did was a rental
//just show the screen
//else, reload rentals
System.out.println("Rentals was selected");
displayError("Rentals was pressed");
// if(rental){
// System.out.println("It's a rental!");
// popScreen(getActiveScreen());
// pushScreen(_offeringsScreen);
// }else{
// System.out.println("Getting Rentals from scratch");
// RentalsThread _rThread = new RentalsThread();
// _rThread.start();
// }
}};
I'm at a complete loss here: The device debugger doesn't seem to even register me selecting the menu item, and not a single line of code executes! It just freezes! I'll try putting back in my RentalsThread call in the start of my program (which was also freezing) just to see if I can tease apart the problem with the Rentals Thread (which makes the Rental Screen), and the problem with the Rentals menu item.
Okay, I think I have this figured out.
1.) My code was still behaving identically even after commenting out everything because I wasn't rebuilding the .COD files (they automatically rebuild if you try to run it in the simulator, but don't when you're generating a .ALX file, for some reason).
2.) The code I had for generating the Rental Screen was adding things to said screen. Apparently this is all well and good on the simulator, but on the real device it's required that you do all graphics manipulation (even for graphics not yet displayed) in an event thread (I used invokeAndWait).
So, now everything seems to be working just fine. There wasn't anything wrong with my networking (nor did I think there was, because my other networking screen works just fine). I still don't know why I get all those weird tunneling network things before I start, but it doesn't seem to affect anything yet.
See also:
BlackBerry UI Threading - The Very Basics
BlackBerry threading model
several suggestions:
if you have some background work with resources like file IO or networking, app just may stuck there... provide error handling and try to debug app from device!
code signing, check latest code update for API which require signing. But since there are no errors this is doubtful.
To debug on device, run Blackberry Device Manager, attach phone to usb, in eclipse select project, Context Menu -> Debug As -> Blackberry Device.
See A50 How to Debug and Optimize
UPDATE I see "Tunnel failed" exception, so it's like network connection problem...
See tunnel failed in blackberry bold. why?
How to Configure Full Internet Access On BlackBerry
UPDATE Support - Application stops responding when opening a connection