in my ExtJS 4.1 application I use a websocket connection to remotely insantiate and control ExtJS classes from the server. The client is registered to websocket.onmessage and is waiting for incoming commands.
I defined a simple protocol for that. The server sends a "CREATE classname id". On client side I use Ext.create to instantiate the class. The server then can send commands via the websocket to the object. E.g. "DOSTUFF id". I'm using the dynamic loading mechnism of ExtJS.
In Chrome everything works fine.
The problem with Firefox is, that the second command message (DOSTUFF) is executed BEFORE the object has been created. This leads to an error because the object cannot be found. It seems that the second websocket commandmessage is executed before ExtJS has loaded the file via HTTP-GET.
In my world JavaScript is executed sequentially (I don't use webworkers). I think the call of Ext.create(..) should be executed synchronously with the HTTP-GET in background, shouldn't it?
Here is a "pseudo" trace output of my client application:
ExecuteCommand (Enter): CREATE ("MyClass", "1")
HTTP-GET "MyClass.js"
ExecuteCommand (Enter): DOSTUFF ("1")
ExecuteCommand (Error): DOSTUFF ("1"): Object not found
ExecuteCommand (Enter): CREATE ("MyClass", "1"): OK! Object created!
It makes sense. The GET request is async by default see Firefox doc: https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Synchronous_and_Asynchronous_Requests
To avoid this issue check for object existence and if need be let the server know to resend in a few seconds, and repeat.
Ok, as mentioned by DmitryB the HTTP-GET works asynchronous. After the XMLHttpRequest is sent, the control is passed to the next websocket.onmessage.
I solved this problem by using Ext.require with a callback function before I call Ext.create.
It looks something like that:
ExecuteCommand: CREATE ("MyClass", "1")
Ext.require("MyClass", function(c) {
ExecuteCommand: DOSTUFF (c);
}
Related
I am using cypress to write tests and have a problem which doesn't appear in every test. In some cases it works and I don't know why. So...
The Problem:
I defined a route and alias for it in beforeEach:
beforeEach(function () {
cy.server()
cy.route('GET', '/favourites?funcName=columnPreset', []).as('columnPresetEmpty')
cy.visit('#/search')
})
Stub works fine if http request occured on page load.
But if I perform request responding to click event (modal dialog opens and executes http request) it just appear in commands not makred as stubbed and following cy.wait('#columnPresetEmpty') fails with request timeout.
it('does not work', function () {
cy.get('[data-test=button-gridSettings]').click()
cy.wait('#columnPresetEmpty')
})
At the same time in other tests I have almost similar functionality where request is performed just by clicking on a button, without opening new modal window. It's the only difference.
What am I doing wrong?
The issue might be cypress can not yet fully handle fetch calls. You can disable it the following way but make sure you have fetch polyfill. This will then issue XHR requests which cypress can observe.
cy.visit('#/search', {
onBeforeLoad: (win) => {
win.fetch = null
}
})
More to read here:
https://github.com/cypress-io/cypress/issues/95#issuecomment-281273126
I found the reason causing such behavior. Problem was not in a modal window itself, but code performing second request was called in promise's callback of another request. Something like:
fetch('/initData')
.then(loadView)
And loadView function executed second fetch.
So when I removed loadView from promise's callback both requests become visible for cypress.
For info, I tried it out on my search modal (in a Vue app) and it works ok.
What I did:
created a dummy file named test-get-in-modal.txt in the app's static folder
added an http.get('test-get-in-modal.txt') inside the modal code, so it only runs after the modal is open
in the spec, did a cy.server(), cy.route('GET', 'test-get-in-modal.txt', []).as('testGetInModal') in a before()
in the it() added cy.wait('#testGetInModal') which succeeded
changed to cy.route('GET', 'not-the-file-you-are-looking-for.txt'..., which failed as expected
The only difference I can see is that I cy.visit() the page prior to cy.server(), which is not the documented pattern but seems to be ok in this scenario.
I wanted to analyze the improvement I may see by enabling Async Controllers in Spring Boot over normal controller
So here is my test code. One API returns a Callable and another is normal controller API. Both APIs block for 10secs simulating a long running task
#RequestMapping(value="/api/1",method=RequestMethod.GET)
public List<String> questions() throws InterruptedException{
Thread.sleep(10000);
return Arrays.asList("Question1","Question2");
}
#RequestMapping(value="/api/2",method=RequestMethod.GET)
public Callable<List<String>> questionsAsync(){
return () -> {
Thread.sleep(10000);
return Arrays.asList("Question2","Question2");
};
}
I set up embedded tomcat with this configuration i.e only one tomcat processing thread:
server.tomcat.max-threads=1
logging.level.org.springframework=debug
Expectations for /api/1
Since there is only one tomcat thread, another request will not be entertained untill this is processed after 10secs
Results:
Meet expectations
Expectations for /api/2
Since we are returning a callable immediately, the single tomcat thread should get free to process another request. Callable would internally start a new thread. So if you hit the same api it should also gets accepted.
Results:
This is not happening and untill the callable executes completely, no further request is entertained.
Question
Why is /api/2 not behaving as expected?
#DaveSyer is right, /api/2 is actually behaving as expected.
I assume you are testing the behavior with a web browser. At least Firefox and Chrome are preventing multiple simultaneous requests to the same URL. If you open 2 tabs with api/2, the second one will only send a request to the application after the first got the response.
Try testing it with a simple bash script, like:
curl localhost/api/2 &
curl localhost/api/2 &
curl localhost/api/2 &
It will print 3 responses around the same time.
Just want to mention that server.tomcat.max-threads is deprecated since Spring boot 2.3. Now use server.tomcat.threads.max in your Spring application.properties. The default is 200.
I downloaded the red5-recorder (http://www.red5-recorder.com/) , which fails to allow me to start recording. After debugging I found that the netconnection, needed to record to a media server, created does not fire a NetStatusEvent event, so essentially it fails silently. I have implemented the connection with the following minimal working example:
trace("make net connection");
nc = new NetConnection();
nc.client = { onBWDone: function():void{ trace("bandwidth check done.") } };
trace("add event listener");
nc.addEventListener(NetStatusEvent.NET_STATUS, function(event:NetStatusEvent) {
trace("handle");
});
trace("connect!");
nc.connect("rtmp://localshost/oflaDemo/test/");
trace("connect done");
The output of this piece of code is:
make net connection
add event listener
connect!
connect done
The actionscript api states that the connect-call always fires such an event:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetConnection.html#includeExamplesSummary
Moreover, the netconnection is not 'connected' (a state of the NetConnection object) 10 seconds after the call. I also took a look at this: NetConnect fails silently in Flash when called from SilverLight But the fix suggested by the author, swapping rtmp and http in the connection uri, do not work. Also, I tested the uri and in fact the exact same code sniplet in a personal project, where it did work. I just can not seem to find why connecting to a media server fails silently in the red5-recorder project.
The awkward part is that if I pass some random string as a conenction uri, still nothing happens (no event, no exception, no crash). Also not setting nc.client becore nc.connect(), which caused exceptions in my experience, did not cause exceptions.
Any suggestions are welcome.
You are setting the address to localshost instead localhost.
nc.connect("rtmp://localshost/oflaDemo/test/");
Correct address:
nc.connect("rtmp://localhost/oflaDemo/test/");
I have a Flex application that connects to a BlazeDS server using the StreamingAMF channel. I want to detect on the server side in case the browser is closed. I have added an implementation for FlexClientListener & registered it to the FlexClient (FlexContext.getFlexClient().addClientDestroyedListener)
But the clientDestroyed method of Listener is not invoked on browser close. It gets invoked on Session timeout. Is there any other way to achieve this?
You won't be able to detect browser interactions on a client from the server.
Your best guess is to make use of ExternalInterface. It allows your Flash app to communicate with JavaScript, and vice versa.
Use the JavaScript onClose event to trigger some JavaScript which will call a function in your Flash App which will make a remote call to let your server side know that the browser is being closed.
We too had similar issue, not closing the session was causing memory leak in BlazeDS, We wrote the below script in swf wrapper javascript, to make ensure that closing browser invokes session closure code in flex
<script language="JavaScript" type="text/javascript">
function cleanup()
{
getMyApplication("swf_filename_without_extension").cleanUp();
alert("Disconnected! Press OK to continue.");
}
function getMyApplication(appName)
{
if (navigator.appName.indexOf ("Microsoft") != -1)
{
return window[appName];
}
else
{
return document[appName];
}
}
</script>
<body onbeforeunload="cleanup()">
In Flex add a call back on creation complete listener
ExternalInterface.addCallback("cleanUp",cleanUp);
and write all your session closure code in cleanUp method.
Note: don't forget to put the alert message in javascript. That will give enough time for cleanUp method to execute.
I have long poll Ajax request. Browser, at least but not last IE doesn't terminate the request at page leaving, so request remains open and active even if a user visits some other site. Say more, a browser can successfully process responses from this connection, although their result go nowhere. General recommendations as call htmlxml connection abort or stop for a window obviously do not work.
So my implementation is adding extra Ajax call on unload to notify server connection holder that page is on leave, so it can send some dummy response and a browser will return the connection to pool of available after. This approach works but looks for me over engineered. Unfortunately I can observe a similar problem with some other programs, like GMAIL, it also does long poll and as result after some reloading it stops working. So if somebody found some good approach to address the problem without switching to short poll or assign connection timeout, then share your solution.
There's an abort() method on IE's XHR which will manually disconnect it.
It's a bit hacky, but you could try something like:
<body onbeforeunload="AbortMyAjax()">
and use that method to abort any active long-polls.
For reference, here's a bit of code from a project of mine:
$this.lp = null;
function _LongPoll() {
$.ajaxSetup({ cache: false });
$this.lp = $.getJSON(m_PollUrl, _LongPollCallback);
}
And in the body beforeunload:
if(!!QueueManager.lp && !!QueueManager.lp.abort) QueueManager.lp.abort('PAGE_CLOSED');