JavaFX WebView / WebEngine - webview

I have a JavaFX WebView that is being updated with background messages and executes scripts to update the page.
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
try {
webEngine.executeScript("foo1();");
} catch (Exception e) {
// JSException: TypeError: 'undefined' is not a function
}
}
}
});
This normally runs correctly, however when I create a second WebView with it's own WebEngine and try and execute foo2() on that second page, at about the same time as execution foo1 on the first page, I get this:
JSException: TypeError: 'undefined' is not a function
I could have a synchronization block, but it seems it should be unnecessary since the webEngines are suppose to be independent, are there other solutions?

This is a session management error in your program.
2 WebViews compete for the same session, and ... assuming you haven't implemented protocol and session handlers, including cookie storage, etc..., the second webengine which is unable to obtain the connection will run the script over something that doesn't exist ( as far as the webengine is concerned ) hence an UNDEFINED object.. thus the error.
I'm using this stuff over HTTPS protocols, and have experienced this.

Related

How to test entity framework execution strategy?

We have an Entity Framework execution strategy coded in our lower environment. How do we test this to show it's actually working? We don't want to release to Prod without something to say we aren't introducing new problems.
The easy way is to use some listener where you can throw an exception and subscribe this listener to the dbContext.
public class CommandListener
{
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting")]
public void OnCommandExecuting(DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, bool async, DateTimeOffset startTime)
{
throw new TimeoutException("Test exception");
}
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted")]
public void OnCommandExecuted(object result, bool async)
{
}
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandError")]
public void OnCommandError(Exception exception, bool async)
{
}
}
Subscribe listener to dbContext f.i. in Startup.cs
var context = provider.GetService<SomeDbContext>();
var listener = context.GetService<DiagnosticSource>();
(listener as DiagnosticListener).SubscribeWithAdapter(new CommandListener());
As TimeoutException is transient exception in SqlServerRetryingExecutionStrategy.cs (if you use the default retrying strategy) you will get TimeoutException as many as your MaxRetryingCount of strategy setting has. Finally, you have to get RetryLimitExceededException as a result of the request.
You have to see TimeoutException in your app logs. Also it is good idea to turn on transaction logs "Microsoft.EntityFrameworkCore.Database.Transaction": "Debug"
What I did to manage to throw the transient exception and debug strategy (testing and playing around purpose only)
I added ExectuionStrategyBase.cs and
TestServerRetryingExecutionStrategy.cs. The first one is clone of
ExectuionStrategy.cs and second one is clone of
SqlServerRetryingExecutionStrategy.cs
In Startup.cs I set retrying strategy
strategy services.AddDbContext<SomeDbContext>(options =>
{options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), sqlOption =>
{
sqlOption.ExecutionStrategy(dependencies =>
{
return new TestSqlRetryingStrategy(
dependencies,
settings.SqlMaxRetryCount,
settings.SqlMaxRetryDelay,
null);
});
});
In OnCommandExecuting of CommandListener.sc I just checked some static bool variable to throw or not TimeoutException and in ExectuionStrategyBase.cs I swithced that variable.
Thus, I managed to throw transient Exception on the first execution of the query and successful execution on the second short. Now I think about some long running transaction and kill session of this transaction in SSCM during execution of it.
Also, I found out that if there is a query like
var users = context.Users.AsNoTracking().ToArrayAsync() execution strategy is not implemented and I am stuck on it. I have been struggling with that a couple of days but still can figure out nothing. If remove AsNoTracking or replace ToArrayAsync() by something like FirstAsync() all foes well.

Detach event in Vaadin web app not getting called

My question stems from an issue almost identical to the one here (which did not end up getting a satisfactory answer):
https://vaadin.com/forum/thread/13932610
Like this person, I expected that upon closing the browser that my app was open in, a detach event would proc; however, this did not happen. I've tried adding a detach listener, overriding the detach method, and doing both at the same time, but none of them were successful. As for how I know the detach event was not called, my detach event is a simple print statement - that does not show up in the output.
Note that like in the aforementioned thread, I've already set the heartbeat interval (2 seconds in my case) and set closeIdelSessions to be true. So, I thought I would just have to wait six seconds, but that's certainly not been the case.
When I try this (find the essential parts of the code below), the detach() is eventually being called. I run this with Jetty, and I did not touch its default. It tooks some ~45 minutes after closing the Browser, when I saw "Detach called" logged on console. So yes, the time is lengthy. The reason is that the last UI is cleaned up only after HttpSession is expired (which depends on application container etc. settings). If you want to do forced clean up quicker, you need to use https://vaadin.com/directory/component/cleanupservlet-add-on
#Push
#SuppressWarnings("serial")
public class DemoUI extends UI {
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = DemoUI.class, heartbeatInterval=5, closeIdleSessions=true)
public static class Servlet extends VaadinServlet {
}
#Override
public void detach() {
System.out.println("Detach called");
}
#Override
protected void init(VaadinRequest vaadinRequest) {
...
}

catch any error in angular dart (like angular's ErrorHandler)

I need to catch any front end (angulardart) error and send it back to the server.
I saw there is something like his in regular Angular ErrorHandler, but I can't find any equivalent in angular dart (or dart it self).
Maybe I should hack the Exception object's constructor, but I don't find it a good approach (assuming it's possible)
any hints please?
In Dart it's quite similar:
#Injectable()
class ErrorHandler implements ExceptionHandler {
ApplicationRef _appRef;
ErrorHandler(Injector injector) {
// prevent DI circular dependency
new Future<Null>.delayed(Duration.ZERO, () {
_appRef = injector.get(ApplicationRef) as ApplicationRef;
});
}
#override
void call(dynamic exception, [dynamic stackTrace, String reason]) {
final stackTraceParam = stackTrace is StackTrace
? stackTrace
: (stackTrace is String
? new StackTrace.fromString(stackTrace)
: (stackTrace is List
? new StackTrace.fromString(stackTrace.join('\n'))
: null));
_log.shout(reason ?? exception, exception, stackTraceParam);
// We can try to get an error shown, but don't assume the app is
// in a healthy state after this error handler was reached.
// You can for example still instruct the user to reload the
// page with danger to cause hare because of inconsistent
// application state..
// To get changes shown, we need to explicitly invoke change detection.
_appRef?.tick();
}
}
Provide the error handler
return bootstrap(AppComponent, [const Provide(ExceptionHandler, useClass: ErrorHandler)]);
For errors that might be caused outside Angular, see also How to catch all uncaught errors in a dart polymer app?

Does detach() method call after attach() method?

I have a simple UI class
public class HelloWorldUI extends UI {
#Override
protected void init(VaadinRequest request) {
System.out.println("Initialized !");
final VerticalLayout layout = new VerticalLayout();
layout.addComponent(new Label("Hello World !"));
setContent(layout);
}
#Override
public void detach() {
System.out.println("Detach !");
super.detach();
}
#Override
public void attach() {
System.out.println("Attach !");
super.attach();
}
}
When first time my UI was loaded , I see outputs at my console as
Attach !
Initialized !
It is OK and this is what I expected. But when I refresh the browser , my console outputs were
Attach !
Initialized !
Detach !
Amazing ! I think Detach ! may be produce first because (as I think) when browser was refreshed , detach() method should be call and attach() , init() should be follow . But actually detach() method will call after attach() method. What's wrong my thinking ?
Browser Refresh = New UI Instance
When you refresh a browser window or tab, a new UI instance is created. So you see an attach message of a new UI instance. The old UI instance will be detached later.
This is default behavior in Vaadin 7. You may change that behavior with an annotation.
#PreserveOnRefresh
Adding #PreserveOnRefresh annotation to the UI changes the behavior: No new UI instance won't be created on refresh.
To quote the doc for this annotation:
Marks a UI that should be retained when the user refreshed the browser window. By default, a new UI instance is created when refreshing, causing any UI state not captured in the URL or the URI fragment to get discarded. By adding this annotation to a UI class, the framework will instead reuse the current UI instance when a reload is detected.

Streaming text output for long-running action?

I have a few utility actions that return text output via return Content("my text","text/plain").
Sometimes these methods take a few minutes to run (i.e. log parsing, database maintenance).
I would like to modify my action method so that instead of returning all of the output at once, the text is instead streamed to the client when it is ready.
Here's a contrived example:
public ActionResult SlowText()
{
var sb = new System.Text.StringBuilder();
sb.AppendLine("This happens quickly...");
sb.AppendLine("Starting a slow 10 second process...");
System.Threading.Thread.Sleep(10000);
sb.AppendLine("All done with 10 second process!");
return Content(sb.ToString(), "text/plain");
}
As written, this action will return three lines of text after 10 seconds. What I want is a way to keep the response stream open, and return the first two lines immediately, and then the third line after 10 seconds.
I remember doing this 10+ years ago in Classic ASP 3.0 using the Response object. Is there an official, MVC-friendly way to accomplish this?
--
Update: using Razor .cshtml in the app; but not using any views (just ContentResult) for these actions.
Writing directly to the Response object should work, but only in some simple cases. Many MVC features depend on output writer substitution (e.g. partial views, Razor view engine, and others) and if you write directly to the Response your result will be out of order.
However, if you don't use a view and instead write straight in the controller then you should be fine (assuming your action is not being called as a child action).
I would skip the MVC controller entirely since you are going to break encapsulation anyway. In it's place I'd use a barenaked IHttpHandler implementation, streaming directly to the aforementioned output stream.
You are exposing yourself to a browser timeout if the process takes longer than originally intended. Then you don't have a way to recover what happened / unless you implement a separate method that gives the information on the long running process.
Given that you want the other method anyway, you can start a long running process and return immediately. Have the browser check the other method that gives the latest information on the long running process. On the last time I had to do this, I kept it simple and just set the refresh header from the controller before returning the view.
As for starting a long running process, you can do something like this:
// in the controller class
delegate void MyLongProcess();
//...
// in the method that starts the action
MyLongProcess processTask = new MyLongProcess(_someInstance.TheLongRunningImplementation);
processTask.BeginInvoke(new AsyncCallback(EndMyLongProcess), processTask);
//...
public void EndMyLongProcess(IAsyncResult result)
{
try{
MyLongProcess processTask = (MyLongProcess)result.AsyncState;
processTask.EndInvoke(result);
// anything you needed at the end of the process
} catch(Exception ex) {
// an error happened, make sure to log this
// as it won't hit the global.asax error handler
}
}
As for where do you put the log of the actions that happened, it's up to you to how long lived you want it to be. It can be as simple as a static field/class where you add the info of the ongoing process, or instead saving it to a data store where it can survive an application recycle.
The above assume this is all about a long running process that goes on reporting the actions that has been done. Streaming is a different subject, but the above might still play a role in keeping the operations in your controller & only the piece responsible of streaming what becomes available to the client in the action result.
You can implement your custom ActionResult like ContentStreamingResult and use HttpContext, HttpRequest and HttpResponse in the ExecuteResult method.
public class ContentStreamingResult : ActionResult
{
private readonly TextReader _reader;
public ContentStreamingResult(TextReader reader)
{
_reader = reader;
}
public override void ExecuteResult(ControllerContext context)
{
var httpContext = context.HttpContext;
//Read text from the reader and write to the response
}
}
public class YourController : Controller
{
public ContentStreamingResult DownloadText()
{
string text = "text text text";
return new ContentStreamingResult(new System.IO.StringReader(text));
}
}
Try Response.Flush and BufferOutput to false. Note it would work with the different action results, you have to directly write into the response object. Probably you can use it with conjunction with AsyncController.

Resources