How to correctly start embedded JavaFX applet with specific JVM arguments - applet

I have written a JavaFX application that includes device interaction via JNA and have no issues running it as a standalone application but when embedded within a browser, and over an extended period of time, the application gradually slows down and eventually stops responding. Using JVisualVM to profiling and monitoring the application, I can see the heap growing out of control before run out of memory and the old gen memory space full.
I was able to find another question which suggests passing arguments to the VM to force more frequent garbage collection. However I have not been able to test the suggestion due to the jvm arguments not sticking.
Modifying the MyJavafxApp.html as below:
function javafxEmbed() {
dtjava.embed(
{
id: 'myApp',
url : 'demo_javafx.jnlp',
placeholder : 'javafx-app-placeholder',
width : '1100',
height : '800',
jnlp_content : 'PD94...'
},
{
jvm: "1.6.0+",
javafx : '2.2+',
jvmargs: "-XX:MaxDirectMemorySize=128M -Xmx256m"
},
{}
);
}
I am unable to see the parameters as JVM Flags or JVM arguments
Rather they are displayed in JVisualVM under the System properties tab and under UsageTracker-AppName as a single string
UsageTracker-AppName=http://localhost:8000/target/web/demo_javafx.html: java_status_events=true jnlp_href=demo_javafx.jnlp separate_jvm=true jnlp_embedded=PD94... java_arguments=-DXX:MaxDirectMemorySize=32m,-Xmx128m,-Xms32m width=1375 javafx_version=2.2+ code=dummy.class type=application/x-java-applet id=myApp javafx_applet_id=myApp height=1000 scriptable=true codebase=http://localhost:8000/target/web/
How would I start the JVM with the arguments?
Note: I shortened the jnlp_content string. I also tried to pass the jvmargs with the -D flag and without.

In your JNLP file you can pass VM parameters like this:
<j2se version="1.6+" java-vm-args="-Djnlp.fx=2.1+ -Djnlp.tk=swing" />
I also found that some of these parameters can be passed as applet-parameters:
<applet ...>
<param name="javafx_version" value="2.1+" />
<param name="scriptable" value="true" />
</applet>
Passing it to dtjava.embed() should work too.
In Deploying JavaFX Applications is described how:
var app = new dtjava.App(
'ssh.jnlp',
{
id: 'SSH',
width: 100,
height: 25,
placeholder: 'SSH_application_container',
params: {
config: 'ssh_application.conf',
}
}
);
var platform = new dtjava.Platform({
javafx: "2.1+",
jvmargs: "-Dapp.property= ? -Xmx1024m"
});
dtjava.launch(app, platform);
The syntax you used should work too. Maybe it is just a question about which parameter to put where (as in app-parameter or vm-parameter). It also seems that the same parameter can have different names when passed in by different ways (eg. javafx: "2.1+", <param name="javafx_version" value="2.1+" /> -Djnlp.fx=2.1+), but maybe they also do different things.

Related

Stop huge error output from testing-library

I love testing-library, have used it a lot in a React project, and I'm trying to use it in an Angular project now - but I've always struggled with the enormous error output, including the HTML text of the render. Not only is this not usually helpful (I couldn't find an element, here's the HTML where it isn't); but it gets truncated, often before the interesting line if you're running in debug mode.
I simply added it as a library alongside the standard Angular Karma+Jasmine setup.
I'm sure you could say the components I'm testing are too large if the HTML output causes my console window to spool for ages, but I have a lot of integration tests in Protractor, and they are SO SLOW :(.
I would say the best solution would be to use the configure method and pass a custom function for getElementError which does what you want.
You can read about configuration here: https://testing-library.com/docs/dom-testing-library/api-configuration
An example of this might look like:
configure({
getElementError: (message: string, container) => {
const error = new Error(message);
error.name = 'TestingLibraryElementError';
error.stack = null;
return error;
},
});
You can then put this in any single test file or use Jest's setupFiles or setupFilesAfterEnv config options to have it run globally.
I am assuming you running jest with rtl in your project.
I personally wouldn't turn it off as it's there to help us, but everyone has a way so if you have your reasons, then fair enough.
1. If you want to disable errors for a specific test, you can mock the console.error.
it('disable error example', () => {
const errorObject = console.error; //store the state of the object
console.error = jest.fn(); // mock the object
// code
//assertion (expect)
console.error = errorObject; // assign it back so you can use it in the next test
});
2. If you want to silence it for all the test, you could use the jest --silent CLI option. Check the docs
The above might even disable the DOM printing that is done by rtl, I am not sure as I haven't tried this, but if you look at the docs I linked, it says
"Prevent tests from printing messages through the console."
Now you almost certainly have everything disabled except the DOM recommendations if the above doesn't work. On that case you might look into react-testing-library's source code and find out what is used for those print statements. Is it a console.log? is it a console.warn? When you got that, just mock it out like option 1 above.
UPDATE
After some digging, I found out that all testing-library DOM printing is built on prettyDOM();
While prettyDOM() can't be disabled you can limit the number of lines to 0, and that would just give you the error message and three dots ... below the message.
Here is an example printout, I messed around with:
TestingLibraryElementError: Unable to find an element with the text: Hello ther. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
...
All you need to do is to pass in an environment variable before executing your test suite, so for example with an npm script it would look like:
DEBUG_PRINT_LIMIT=0 npm run test
Here is the doc
UPDATE 2:
As per the OP's FR on github this can also be achieved without injecting in a global variable to limit the PrettyDOM line output (in case if it's used elsewhere). The getElementError config option need to be changed:
dom-testing-library/src/config.js
// called when getBy* queries fail. (message, container) => Error
getElementError(message, container) {
const error = new Error(
[message, prettyDOM(container)].filter(Boolean).join('\n\n'),
)
error.name = 'TestingLibraryElementError'
return error
},
The callstack can also be removed
You can change how the message is built by setting the DOM testing library message building function with config. In my Angular project I added this to test.js:
configure({
getElementError: (message: string, container) => {
const error = new Error(message);
error.name = 'TestingLibraryElementError';
error.stack = null;
return error;
},
});
This was answered here: https://github.com/testing-library/dom-testing-library/issues/773 by https://github.com/wyze.

Protractor Custom Locator: Not available in production, but working absolutely fine on localhost

I have added a custom locator in protractor, below is the code
const customLocaterFunc = function (locater: string, parentElement?: Element, rootSelector?: any) {
var using = parentElement || (rootSelector && document.querySelector(rootSelector)) || document;
return using.querySelector("[custom-locater='" + locater + "']");
}
by.addLocator('customLocater', customLocaterFunc);
And then, I have configured it inside protractor.conf.js file, in onPrepare method like this:
...
onPrepare() {
require('./path-to-above-file/');
...
}
...
When I run my tests on the localhost, using browser.get('http://localhost:4200/login'), the custom locator function works absolutely fine. But when I use browser.get('http://11.15.10.111/login'), the same code fails to locate the element.
Please note, that the test runs, the browser gets open, user input gets provided, the user gets logged-in successfully as well, but the element which is referred via this custom locator is not found.
FYI, 11.15.10.111 is the remote machine (a virtual machine) where the application is deployed. So, in short the custom locator works as expected on localhost, but fails on production.
Not an answer, but something you'll want to consider.
I remember adding this custom locator, and encounter some problems with it and realised it's just an attribute name... nothing fancy, so I thought it's actually much faster to write
let elem = $('[custom-locator="locator"]')
which is equivalent to
let elem = element(by.css('[custom-locator="locator"]'))
than
let elem = element(by.customLocator('locator'))
And I gave up on this idea. So maybe you'll want to go this way too
I was able to find a solution to this problem, I used data- prefix for the custom attribute in the HTML. Using which I can find that custom attribute on the production build as well.
This is an HTML5 principle to prepend data- for any custom attribute.
Apart from this, another mistake that I was doing, is with the selector's name. In my code, the selector name is in camelCase (loginBtn), but in the production build, it was replaced with loginbtn (all small case), that's why my custom locater was not able to find it on the production build.

Babel plugins run order

TL;DR: Is there a way how to specify the order in which the Babel plugins are supposed to be run? How does Babel determine this order? Is there any spec how this works apart from diving into Babel sources?
I'm developing my own Babel plugin. I noticed, that when I run it, my plugin is run before other es2015 plugins. For example having code such as:
const a = () => 1
and visitor such as:
visitor: {
ArrowFunctionExpression(path) {
console.log('ArrowFunction')
},
FunctionExpression(path) {
console.log('Function')
},
}
my plugin observes ArrowFunction (and not Function). I played with the order in which the plugins are listed in Babel configuration, but that didn't change anything:
plugins: ['path_to_myplugin', 'transform-es2015-arrow-functions'],
plugins: ['transform-es2015-arrow-functions', 'path_to_myplugin'],
OTOH, this looks like the order DOES somehow matter:
https://phabricator.babeljs.io/T6719
---- EDIT ----
I found out that if I write my visitor as follows:
ArrowFunctionExpression: {
enter(path) {
console.log('ArrowFunction')
}
},
FunctionExpression: {
exit(path) {
console.log('Function')
}
},
both functions are called. So it looks like the order of execution is: myplugin_enter -> other_plugin -> myplugin_exit. In other words, myplugin seems to be before other_plugin in some internal pipeline. The main question however stays the same - the order of plugins in the pipeline should be determined & configurable somehow.
The order of plugins is based on the order of things in your .babelrc with plugins running before presets, and each group running later plugins/presets before earlier ones.
The key thing though is that the ordering is per AST Node. Each plugin does not do a full traversal, Babel does a single traversal running all plugins in parallel, with each node processed one at a time running each handler for each plugin.
Basically, what #loganfsmyth wrote is correct; there is (probably) no more magic in plugin ordering itself.
As for the my problem specifically, my confusion was caused by how arrow function transformation works. Even if the babel-plugin-transform-es2015-arrow-functions plugin mangles the code sooner than my plugin, it does not remove the original arrow-function ast node from the ast, so even the later plugin sees it.
Learning: when dealing with Babel, don't underestimate the amount of debug print statements needed to understand what's happening.

Deferred binding not working after compilation

I have a weird problem with deferred binding. I have defined the following module:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Defines the usercategory property and its provider function. -->
<module>
<define-property name="usercategory" values="c00,c01,c02" />
<collapse-property name="usercategory" values="*" />
<property-provider name="usercategory"><![CDATA[
// Look for the usercategory cookie
var cs = document.cookie.split(';');
for (var i = 0; i < cs.length; i++) {
var name = cs[i].substr(0, cs[i].indexOf("="));
var value = cs[i].substr(cs[i].indexOf("=") + 1);
name = name.replace(/^\s+|\s+$/g,"");
if (name == "usercategory") {
return unescape(value);
}
}
return "c00";
]]></property-provider>
</module>
which sets the property usercategory by looking at the value of a cookie named usercategory.
I use this property application.gwt.xml to defer binding of some classes, for example:
<inherits name="com.example.UserCategory"/>
<replace-with class="com.example.client.ui.menu.MainMenuView01">
<when-type-is class="com.example.client.ui.menu.MainMenuView"/>
<when-property-is name="usercategory" value="c01"/>
</replace-with>
This works like a charm when I'm in development mode (i.e. when running my app from within Eclipse). However, if I compile the app and deploy it (in Jetty, but I don't this this is the problem), then deferred binding does not seem to work, and the expected classes are not loaded. I've checked and the cookie is set up properly with the correct value c01, but class com.example.client.ui.menu.MainMenuView01 is not loaded.
Am I missing something? Am I doing something wrong?
Thank you in advance!
There are two possibilities. You are doing something wrong, or there is another bug in GWT compiler. I've tried to implement a case like your and it was working when compiled without any problems. So most likely there can be some error on your side. So what i recommend to do is to compile app with -style PRETTY and see how it was compiled. find function named com_example_client_ui_menu_MainMenuView(), and see if it able to create MainMenuView01, try to debug it and etc. Anyway this kind of stuff should be working without any problems.
Also try to debug your property provider (and use vars $doc and $wnd in property provider instead of window)
Another possible case is that the cookie might be not readable from JS
I figured out what the problem was, and I'm writing it here in case others might be interested.
The module that I defined (see code in my question) defines a property whose value is taken from a cookie, that is generated after the user logs in the application.
Originally I had a GWT Place for the login, and when the user successfully authenticated the application moved to another Place. In this case when the user enter the application, and the GWT Javascript is downloaded to the browser, the cookie is not set yet (because the user has not performed login yet). Therefore the deferred binding does not work, and the expected classes (like com.example.client.ui.menu.MainMenuView01) are not loaded.
I have no idea why this works correctly when run in development mode. Anyway. the solution that I implemented is to move the login phase outside of the GWT application, and when the login is successful, I add the cookie and the redirect the user to the actual GWT application.

Eclipse eRCP command framework - Unable to update command label dynamically

I've scoured the web for the entire day trying to find an example on how to implement what I read concerning changing a command label dynamically here:
http:// wiki.eclipse.org/Platform_UI_Command_Design#Issue_102_-_Comm ands_implementation_of_label_changing
I have the a command defined in my plugin.xml that uses the suggested schema:
<command
description="Hoping to change my state"
id="my.commandWithState"
name="Command Wtih State">
<state
class="org.eclipse.jface.menus.TextState"
id="NAME"/>
</command>
In my handler, I have tried a lot of variations (including calling "getValue" before trying to set it in hopes of forcing a load to be called), but basically the gist is:
public Object execute(final ExecutionEvent pEvent) throws ExecutionException {
pEvent.getCommand().getState("my.commandWithState").setValue("UPDATED!");
return null;
}
The state value itself is updated, but not persisted. I specified a style of "push" in the menuContribution area of my plugin.xml and the text on the command is always "Command With State" since I did not specify a label (though i expected it to change...)
I'm using Eclipse 3.6 so I assume I have the updates that supposedly allow this from 3.3.
The only way I have been able to set the text on the command ui object is to have my handler implement IElementUpdater like I'm working with a ToggleState. This allows me to change the text a total of 1 time, when I first start the product.
I'm about to tear my hair out.
1) The command "label" is not updated and
2) the state value is not persisted even though TextState extends PersistedState.
What d>_