This discussion is archived
7 Replies Latest reply: Apr 30, 2013 2:32 PM by cr0ck3t RSS

can I launch a javafx thread from a main thread?

cr0ck3t Newbie
Currently Being Moderated
EDIT: what I want the code to achieve:
1) Controller class
- runs in the background
- creates the shopping cart
- creates listeners for applications which are going to add items to the shopping cart
- will regulate which application has access to the screen
2) ShoppingCart class
- runs in the background
- recieves items from non-Java based applications
- stores these items "in the cart"
3) Checkout class
- GUI for user to remove items from their cart
- will complete the transaction before returning control to the shopping cart

I'm new to javafx - and have not used java in years, to wit, I am attempting the following:

-------------------------------------------------------------------------------------------------------------------------------
Controller Class
-------------------------------------------------------------------------------------------------------------------------------
public class Controller {
     private static ShoppingCart shoppingCart;

     public static void main(String[] args) {
          ExecutorService exec = Executors.newFixedThreadPool(5);
          try {
               shoppingCart = new ShoppingCart(2001);
               exec.execute(shoppingCart);
          } catch (IOException ex) {
               ex.printStackTrace();
          }
     }
}
-------------------------------------------------------------------------------------------------------------------------------
ShoppingCart Class
-------------------------------------------------------------------------------------------------------------------------------
public class ShoppingCart extends Stage implements Runnable {
     private ServerSocket serverSocket;
     private Socket clientSocket;
     private Socket socket;
     private final int port;
     
     private BufferedReader bReader;
     private BufferedWriter bWriter;
     
     private final ArrayList<String> items = new ArrayList<Item>();

    public ShoppingCart(int port) throws IOException {
          this.port = port;
    }
     
     /*
      * when an item arrives at the port, pass the port through to RecieveItem to digest the incomming stream
      */
    @Override
    public void run() {
          
          boolean addMoreItems = true;
          try {
               this.serverSocket = new ServerSocket(port);
          } catch (IOException ex) {
               ex.printStackTrace();
          }
          try {
               while(addMoreItems){
                    this.clientSocket = serverSocket.accept();
                    String theItem = receiveItem(clientSocket);
                    if(theItem == null)
                         addMoreItems = false;
                    else
                         this.items.add(theItem);
               }
          } catch (IOException ex) {
               ex.printStackTrace();
          }
    }

    private String receiveItem(Socket socket) throws IOException {
          String readLine = "";
          String itemString = "";
          
          this.socket = socket;
          this.bReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
          
          while(readLine != null){
               readLine = bReader.readLine();
               // if we are finished adding items, proceed to checkout
               if(readLine.equalsIgnoreCase("checkout")) {
                    // show cart for user to see items before paying
                    itemString = null;
               } else { // otherwise, add the item
                    itemString += "|" + readLine;
               }
          }
          
          return itemString;
     }
-------------------------------------------------------------------------------------------------------------------------------
When I try to run the code, I get the following:
-------------------------------------------------------------------------------------------------------------------------------
Exception in thread "main" java.lang.IllegalStateException: Not on FX application thread; currentThread = main
-------------------------------------------------------------------------------------------------------------------------------

So, is this possible? What am I missing?
Thanks for reading my issues :)
Dave.

Edited by: 1003225 on 29-Apr-2013 20:26

Edited by: 1003225 on 30-Apr-2013 12:49
  • 1. Re: can I launch a javafx thread from a main thread?
    jsmith Guru
    Currently Being Moderated
    You can launch a Java application from the main thread by invoking Application.launch.
    http://docs.oracle.com/javafx/2/api/javafx/application/Application.html#launch%28java.lang.Class,%20java.lang.String...%29

    There is a very strict caveat on it =>
    "Launch a standalone application. This method is typically called from the main method(). It must not be called more than once or an exception will be thrown."
    import javafx.application.Application;
    import javafx.scene.*;
    import javafx.scene.control.*;
    import javafx.stage.Stage;
    
    public class Hello extends Application {
      public static void main(String[] args) throws Exception { launch(args); }
      @Override public void start(final Stage stage) throws Exception {
        stage.setScene(new Scene(new Label("Hello")));
        stage.show();
      }
    }
    I'm kind of lost as to what your program has to do with JavaFX as there is no JavaFX code in it other than the ShoppingCart extending Stage and then doing a bunch of socket stuff, which is a weird thing to do in something that extends Stage. Normally if you want to do socket based stuff, you want to do it off of the JavaFX thread using a Task or Service (you seem to want to use executors, so perhaps a service would be best for you). However, in your case, seeing as you can't even run an application, I'd get the application running and doing a bunch of other stuff first before trying to tackle concurrent tasks with it.

    http://docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html
    http://docs.oracle.com/javafx/2/api/javafx/concurrent/Service.html

    See how to post code: https://forums.oracle.com/forums/ann.jspa?annID=1622
  • 2. Re: can I launch a javafx thread from a main thread?
    cr0ck3t Newbie
    Currently Being Moderated
    Thanks JSmith!

    I had actually developed the application first and am now moving it into threads so I can actually listen for data being sent to it from non java applications... I had initially shown the shopping cart contents via ShoppingCart, but am now creating another class called Checkout to do this.

    I posted the question while I was refactoring the code, as I knew I did not know how to achieve this. Will be using your input to create an instance of Checkout and will let you know how it goes - looks like what I am looking for though :)

    Thanks again,
    Dave.

    Edited by: 1003225 on 29-Apr-2013 20:30
  • 3. Re: can I launch a javafx thread from a main thread?
    cr0ck3t Newbie
    Currently Being Moderated
    I thought I saw a way arround the caveat you mentioned, but no luck.

    What I want to do is have the Java Application spawn a JavaFX 'Checkout' where the user is able to edit items in their shopping cart before submitting a transaction. I have been unable to find a way to 'hide' the stage, but need to do this as another (non Java) application is presenting advertising content which the user selects to put in the shopping cart.

    Any more thoughts are most appreciated.

    ... I think I might also post what I want to do in my initial message...

    Thanks again,
    Dave.
  • 4. Re: can I launch a javafx thread from a main thread?
    cr0ck3t Newbie
    Currently Being Moderated
    So I've changed run() in ShoppingCart to the following:
        @Override
        public void run() {
         for(int i=0;i<5;i++){
              Application.launch(controller.payment.Checkout.jar, items.toString());
              System.out.println("Got Back!");
         }
         try {
              this.serverSocket = new ServerSocket(port);
         } catch (IOException ex) {
              ex.printStackTrace();
         }
    }
    and have added the Checkout class:
    public class Checkout extends Application {
         @Override
         public void start(Stage stage) throws Exception {
              System.out.println("Got there!");
              Platform.exit();
         }
    }
    Which, of course, produces the caveat JSmith mentioned...

    My thoughts are to create a seperate Checkout application, and then:
    - communicate via sockets
    - start and restart the application via:
    - Runtime rt = Runtime.getRuntime();
    - Process pr = rt.exec("java -jar the.Checkout.application");

    But this seams rather crude...

    Edited by: 1003225 on 30-Apr-2013 13:15

    Edited by: 1003225 on 30-Apr-2013 13:24
  • 5. Re: can I launch a javafx thread from a main thread?
    cr0ck3t Newbie
    Currently Being Moderated
    The learning process is always interesting when you are behind the 8-ball with respect to a timeline...

    What you sent me works perfectly :D I just have to show and hide the stage when in/not in use. Thinking I could use some more "Java" if I am going to be trying to use a language I have not used in a while on so little sleep ;)

    Thanks again!
    Dave.
  • 6. Re: can I launch a javafx thread from a main thread?
    cr0ck3t Newbie
    Currently Being Moderated
    Changing 'Helpful' to 'Correct'

    I've done some searching and aparently you would need to repost the same answer for me to be able to show your answer as being correct (for whatever reason, it is not changeable)

    Please do so I am able to award credit where credit is due.

    Thanks again,
    Dave.
  • 7. Re: can I launch a javafx thread from a main thread?
    jsmith Guru
    Currently Being Moderated
    I've done some searching and aparently you would need to repost the same answer for me to be able to show your answer as being correct (for whatever reason, it is not changeable)
    Answer:

    You can launch a Java application from the main thread by invoking Application.launch, but you can only call it once per process or an exception will be thrown:
    http://docs.oracle.com/javafx/2/api/javafx/application/Application.html#launch%28java.lang.Class,%20java.lang.String...%29

    ---------

    Related:

    The lifecycle and management of threads executing user code by the JavaFX application is documented in the JavaFX Application javadoc:
    http://docs.oracle.com/javafx/2/api/javafx/application/Application.html

    Application exit conditions are maintained by Platform.setImplicitExit:
    http://docs.oracle.com/javafx/2/api/javafx/application/Platform.html#setImplicitExit%28boolean%29

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points