open javafx application via rest call - rest

Does anyone know how to open a JavaFx application via rest requests?
Scenario:
I have a Spring Boot Service that runs on every machine to make a bridge wiht my SPA(Single Page Application) and my comm ports. Thats because SPA cannot talk to the OS.
This communications are made via http requests.
Now I have a problem, I need to make a javafx application that is started via http request, when I call the firts time, it works ok, but if i close the javafx application clicking on 'x' and try to open again I'm getting the following error:
java.lang.IllegalStateException: Application launch must not be called more than once
There is a way that when I close the javafx window, it kill the JavaFx Thread, so when I call it again, it start a new Thread?
Or do I need to keep the Thread and just find a way to reopen my javafx application in the same Thread?
here is my #Controller
#RestController
#RequestMapping("v1/appfx")
public class AppfxController{
#RequestMapping("")
private void openJavaFxApp(){
try{
MyJavaFxApp.launch(MyJavaFxApp.class);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
And Here is my JavaFx:
public class MyJavaFxApp extends Application {
private final static Logger log = LoggerFactory.getLogger(MyJavaFxApp.class);
private BigDecimal left;
private String selectedOperator;
private boolean numberInputting;
#FXML
private TextField display;
public MyJavaFxApp() {
this.left = BigDecimal.ZERO;
this.selectedOperator = "";
this.numberInputting = false;
}
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("MyJavaFxApp");
stage.setOnCloseRequest(x -> {
log.info("closed");
Platform.exit();
});
stage.setResizable(false);
stage.setScene(new Scene(FXMLLoader.load(getClass().getClassLoader().getResource("Test.fxml"))));
stage.show();
stage.toFront();
}
}
Thanks for any help.

Related

EJB not initializing in Wildfly 9.0.0 using #EJB

I'm trying to migrate from EJB2.x to EJB3.x and i'm using Wildfly 9.0.0.
The old EJB2.x is working in JBoss 4.2.2 and this is how it looks like:
public interface WUFFacadeRemote extends EJBObject {
public ClientData getItems(ClientData data);
public ClientData save(ClientData data);
}
public interface WUFFacadeHome extends EJBHome {
public WUFFacadeRemote create();
}
public class WUFFacade {
public ClientData getItems(ClientData data) {
//code here
}
public ClientData save(ClientData data) {
//code here
}
}
public class WUFAction extends HttpServlet implements IAction {
public void doPost(HttpServletRequest request, HttpServletResponse response) {
...
Object objRef = ic.lookup("java:comp/env/wUF");
com.wuf.WUFFacadeHome home = (com.wuf.WUFFacadeHome) PortableRemoteObject.narrow(objRef, com.wuf.WUFFacadeHome.class);
engine = home.create();
//engine gets the reference, and I can use it normally.
...
}
}
I also have the ejb-jar.xml and it's working. Now, the solution I was thinking to EJB3.x and Wildfly 9.0.0 is as below:
#WebServlet(urlPatterns = "windows/wUF.do", loadOnStartup = 1)
public class WUFAction extends HttpServlet implements IAction {
#EJB
private WUFFacadeRemote engine;
public void doPost(HttpServletRequest request, HttpServletResponse response) {
//Here I should be able to use my engine.
//Wildfly starts and I call the page, engine is not null at this moment,
//but after I call the page again, it becomes null and remains null.
}
}
#Stateless
#Remote(WUFFacadeRemote.class)
public class WUFFacade extends RootFacade implements WUFFacadeRemote, Serializable {
public WUFFacade() { }
#EJB
FUFHome home;
public ClientData getItems(ClientData data) {
//code here
}
public ClientData save(ClientData data) {
//code here
}
private Col load(ClientData data,InitialContext ic) {
//here i'm calling home.
// but home is always null. It was supposed to have the #EJB reference initialized.
//But instead I get a null pointer...
home.findByFilter(loader);
}
}
#Remote(FUFHome.class)
public interface FUFHome {
FUF create(FUFValue fUFValue);
FUF findByPrimaryKey(FUFPK pk);
Collection findByFilter(FacadeLoader loader);
}
public interface WUFFacadeRemote{
public ClientData getItems(ClientData data);
public ClientData save(ClientData data);
}
I don't have ejb-jar.xml anymore, the deploy is sucessfully done and Wildfly starts with no errors. Then the first time I call the page in question, it seems that #EJB is working (Debug is "Proxy for remote EJB StatelessEJBLocator for "bus-facade/WUFFacade", view is interface com.wuf.WUFFacadeRemote, affinity is None"), the value is not null, but for all subsequent calls, my variable is null and I got a NullPointerException.
I really don't know what i'm doing wrong (maybe i'm completely lost), but to me, #EJB should be working correctly like that. What am I missing? Thanks.
As i'm using EJB3.x i'm just using annotations now, (this seems to be ok).
JNDIs:
JNDI bindings for session bean named FUF in deployment
java:global/fumo/bus-entities-fumo/FUF!apyon.components.fumo.fuf.FUF
java:app/bus-entities-fumo/FUF!apyon.components.fumo.fuf.FUF
java:module/FUF!apyon.components.fumo.fuf.FUF
java:global/fumo/bus-entities-fumo/FUF
java:app/bus-entities-fumo/FUF
java:module/FUF
JNDI bindings for session bean named WUFFacade
java:global/fumo/bus-facade-fumo/WUFFacade!apyon.fumo.wuf.WUFFacadeRemote
java:app/bus-facade-fumo/WUFFacade!apyon.fumo.wuf.WUFFacadeRemote
java:module/WUFFacade!apyon.fumo.wuf.WUFFacadeRemote
java:jboss/exported/fumo/bus-facade-fumo/WUFFacade!apyon.fumo.wuf.WUFFacadeRemote
java:global/fumo/bus-facade-fumo/WUFFacade
java:app/bus-facade-fumo/WUFFacade
java:module/WUFFacade
I think I found a possible solution to the problem. I'll still try to find another one, but this is good so far.
After changing to a .war and keeping my other projects in .ears it's working. Maybe the problem was because I have a RootController servlet im my main.ear, which is the starting point of the aplication. The context starts there and then it redirects to fumo.ear (now fumo.war).
For some reason, I always was getting a null in my EJB after entering a page. It was always hapening when I first entered a JSP and tried to call the page again. My solution to this is:
#WebServlet(urlPatterns = "windows/wUF.do", loadOnStartup = 1)
public class WUFAction extends HttpServlet {
private WUFFacadeRemote engine;
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
doPost(req, resp);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) {
if(engine == null) {
InitialContext ic;
try {
ic = new InitialContext();
engine = (WUFFacadeRemote) ic.lookup("java:global/fumo/WUFFacade!fumo.wuf.WUFFacadeRemote");
} catch (NamingException e) {
e.printStackTrace();
}
}
//here I always have the context now.
}
}
And as a .war my structure now looks like this:
So other annotations like #Inject and #EJB are now working. Always when i'm being redirect from a JSP calling a Servlet or some action, I first check if the context is not null, otherwise I lookup it. My #Stateless are working and the #PersistenceContext and #Remote are working too.
#Stateless
public class WUFFacade implements WUFFacadeRemote {
#Inject
private FUFRules rules;
#EJB
private FUFHome home;
private Col load(ClientData data, InitialContext ic) throws InterfaceException {
try {
// home here is nor null anymore.
Collection res = (Collection) home.findByFilter(loader);
...
} catch (InterfaceException e) {
e.printStackTrace();
}
...
return data;
}
}
So I'd like to thank everyone who helped in the thread. It was a good way to understand and see the problem or to find a workaround. As I said, I'll still try the .ear in the future, but as a simplified packaging it definitely works.

Eclipse RCP Inject into instance of IWizard

I am trying to inject some of my Wizard's fields.
I can successfully inject my own OSGi DS using the following helper class:
public class UtilRCP {
public static void inject(Plugin plugin, Object object) {
IEclipseContext serviceContext = EclipseContextFactory.getServiceContext(plugin.getBundle().getBundleContext());
ContextInjectionFactory.inject(object, serviceContext);
}
}
Other Services from the RCP ecosystem such as PartService or MApplication fail to be injected (null / no actual value was found for the argument "MApplication").
Here is the code
public class MyWizard extends MyAbstractWizard implements IImportWizard {
private MyWizardPage page;
#Inject
private EPartService partService;
#Inject
private DatabaseProvider databaseProvider;
#Inject
private MApplication application;
public MyWizard() {
System.err.println("Create");
System.err.println(databaseProvider);
System.err.println(partService);
System.err.println(application);
}
#Override
public void init(IWorkbench workbench, IStructuredSelection selection) {
UtilRCP.inject(Activator.getDefault(), this);
System.err.println("Init");
System.err.println(databaseProvider);
System.err.println(partService);
System.err.println(application);
}
#Override
public void addPages() {
super.addPages();
page = new MyWizardPage();
addPage(page);
}
#Override
public boolean performFinish() {
return true;
}
}
The service context has very limited contents and is not suitable for use like this.
In a 3.x style wizard like this you can get the workbench context from the IWorkbench object using:
#Override
public void init(IWorkbench workbench, IStructuredSelection selection) {
IEclipseContext context = (IEclipseContext)workbench.getService(IEclipseContext.class);
Note that when a dialog is active there is no active 'part' (because a dialog is not a part). This can cause problems with various APIs. In particular the application (workbench) part service will give an exception complaining that there is no active part.
You can get a working part service by explicitly getting the part service for the top level window using:
#Inject
MApplication application;
#Inject
EModelService modelService;
MWindow window = (MWindow)modelService.find("top level window id", application);
EPartService partService = window.getContext().get(EPartService.class);
I believe the top level window id for a 3.x RCP is "IDEWindow".
If its an E4 application, you can find the main window id in your Application.e4xml.

NullPointerException when I changed all my methods to static

Using Selenium w Java and Test NG (POM format) Switched everything from not static to static and changed everything accordingly, getting NullPointerException. It worked when everything was not static, but making everything static requires less code so I'd prefer to have it that way.
Here is my code.. while trying to paste my code for some reason it did not recognize the import statements as code so I just did not include them, but rest assured everything has been imported that is needed! :)
Package pages;
public class locationPage {
WebDriver driver;
static #FindBy (id="btn_bogota") WebElement chooseBogota;
static #FindBy (id="btn_medellin") WebElement chooseMedellin;
static #FindBy (xpath="//title") WebElement pageTitle;
public locationPage (WebDriver driver){
this.driver=driver;
PageFactory.initElements(driver, this);
}
public static void chooseLocation (String location) {
if (location.equals("Bogota"))
{
chooseBogota.click();
}
else if (location.equals("Medellin")){
chooseMedellin.click();
}
}
}
Package testcases;
public class selectLocation {
WebDriver driver;
#BeforeClass
public void setup() throws InterruptedException{
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://dev01.juanregala.com.co/");
//Generating Alert Using Javascript Executor
JavascriptExecutor javascript = (JavascriptExecutor) driver;
javascript.executeScript("alert('Select Location');");
Thread.sleep(2000);
driver.switchTo().alert().accept();
}
#AfterTest
public void quit(){
driver.quit();
}
#Test (priority=0)
public void location(){
locationPage.chooseLocation("Medellin");
}
}
It keeps giving me a NullPointerException referring to
chooseMedellin.click();
and
locationPage.chooseLocation("Medellin");
I am not really sure how else to describe my issue :( Please help!
You are getting a NullPointerException because the fields are not initialized. You can't use a page object in this way. Even if you could, you probably wouldn't want to since a page object is tied to a particular web driver and that would mean you could never use the same page object among multiple tests and run them in parallel.
Basically, the PageFactory only works on object instances. It won't initialize static fields and, even if it did, you are only calling the page factory from the constructor of your page and that is never being called since you only call a static method on that class.
You need to create an instance of the page object and then pass it to the PageFactory along with the driver that will be running the page object.
Simple example:
public class FooTest {
private WebDriver driver;
private FooPage page;
#BeforeMethod
public void setup() {
driver = new FirefoxDriver();
page = PageFactory.initElements(driver, FooPage.class);
}
#AfterMethod
public void tearDown() {
try {
driver.quit();
} catch ( Exception ignore ) { }
driver = null;
page = null;
}
#Test
public void testFoo() {
}
}
public class FooPage {
#FindBy(id="foo")
private WebElement fooElement;
public void clickFoo() {
fooElement.click();
}
}
Note the line:
page = PageFactory.initElements(driver, FooPage.class);
That method will actually call the default construct of FooPage. You can also instantiate the object yourself and pass it to the page factory like this:
page = new FooPage();
PageFactory.initElements(driver, page);

Java EE6, EJB 3.1 and Socket Client

I'm developing a web application that needs to communicate with any servers (python) by socket. My web application will be the client socket.
I read some alternatives about EJB and Socket. (JCA was indicated, but it is too much for my simple client)
To simplify the solution I was thinking to create an EJB #Singleton and create Threads to work in it.
Do you have some suggestion?
My simple idea:
Singleton
#Startup
#Singleton
public class SingletonBean {
private List<EventMonitor> monitors = new ArrayList<>();
#PostConstruct
private void postConstruct() {
EventMonitor monitor = new EventMonitor("192.168.1.1", 23);
monitors.add(monitor);
monitor.start();
monitor = new EventMonitor("192.168.1.2", 23);
monitors.add(monitor);
monitor.start();
}
}
Monitor
public class EventMonitor extends Thread {
private String host;
private int port;
public EventMonitor(final String host, final int port) {
this.host = host;
this.port = port;
openConnection();
}
#Override
public void run() {
// read socket message and persist
// I think persist here is not a good idea, any better idea?
}
}
Any suggestion?
Thank you for your time.
By the way, the answer was simple like the idea!
Singleton was enough in this case.

Starting Selenium with custom Firefox profile from Eclipse

I'm running Selenium tests from within Eclipse, but I can't load a custom Firefox profile.
Most sources suggest I need to launch the Selenium Server like this:
java -jar selenium-server.jar -firefoxProfileTemplate </path/to/template/>
But when launching my test from within Eclipse it doesn't use that - the tests will run if the Selenium Server isn't running.
This thread suggests that I can set the profile in the DefaultSelenium constructor:
Selenium RC - disabling browser cookie
But the code generated for me by Selenium IDE (Firefox plugin) doesn't use that constructor:
package com.example.tests;
import com.thoughtworks.selenium.*;
import java.util.regex.Pattern;
public class Example extends SeleneseTestCase {
public void setUp() throws Exception {
setUp("http://www.example.com/", "*firefox");
}
public void testExample() throws Exception {
selenium.open("/");
selenium.click("//body");
}
}
Where should I set the DefaultSelenium configuration options? Or is there some other method I can use to load my custom Firefox template?
Thanks!
Stu
I made a SeleniumTestCase that starts/stops the server before/after each test class and starts/stops the Selenium instance before/after each test:
public class SeleniumTestCase {
protected static Selenium selenium;
protected static AppNavUtils appNavUtils;
#BeforeClass
public static void setUpBeforeClass() throws Exception {
SeleniumServerControl.getInstance().startSeleniumServer();
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
SeleniumServerControl.getInstance().stopSeleniumServer();
}
#Before
public void setUp() throws Exception {
// Replace "*chrome" with "*firefox" for Selenium > 1.0
selenium = new DefaultSelenium("localhost", 5444, "*chrome", "http://localhost:8080/");
selenium.start();
appNavUtils = new AppNavUtils(selenium);
}
#After
public void tearDown() throws Exception {
selenium.stop();
}
}
The SeleniumServerControl starts and stops the server:
public class SeleniumServerControl {
private static final SeleniumServerControl instance = new SeleniumServerControl();
public static SeleniumServerControl getInstance()
{
return instance;
}
private SeleniumServer server = null;
protected SeleniumServerControl(){}
public void startSeleniumServer() {
if (server == null) {
RemoteControlConfiguration rcc = new RemoteControlConfiguration();
rcc.setPort(5444);
//rcc.setFirefoxProfileTemplate(newFirefoxProfileTemplate)
server = new SeleniumServer(rcc);
}
server.start();
}
public void stopSeleniumServer()
{
if (server != null) {
server.stop();
server = null;
}
}
}
the version of code you have above assumes that you are running your tests against localhost on port 4444 thats why it is has 2 parameters in the setup.
To set up eclipse to run it you will need to update the run configuration. That is under
Run > Run Configurations
Have a look for the item that has selenium in it and add the config above so that when it runs it will pick it up and run.
I personally just fire up the server when I start working by running a batch file and kill it at the end of the day.