Native Messaging WIP -- print msg queue
authorBill Erickson <berickxx@gmail.com>
Wed, 9 Nov 2016 17:30:34 +0000 (12:30 -0500)
committerBill Erickson <berickxx@gmail.com>
Wed, 9 Nov 2016 17:30:34 +0000 (12:30 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
src/org/evergreen_ils/hatch/Hatch.java
src/org/evergreen_ils/hatch/PrintManager.java
src/org/evergreen_ils/hatch/RequestHandler.java

index 22e553b..d674af6 100644 (file)
@@ -52,6 +52,9 @@ public class Hatch extends Application {
     /** Our logger instance */
     static Logger logger;
 
+    /** Queue of incoming print requests */
+    private static LinkedBlockingQueue<JSONObject> 
+        printRequestQueue = new LinkedBlockingQueue<JSONObject>();
     
     /**
      * Printable region containing a browser.
@@ -65,25 +68,49 @@ public class Hatch extends Application {
     }
 
     /**
+     * Shuffles print requests from the request queue into the 
+     * FX Platform queue.
+     *
+     * This step allows the code to process print requests in order
+     * and without nesting UI event loops.
+     */
+    class PrintRequestShuffler extends Thread {
+        public void run() {
+            while (true) {
+                try {
+                    JSONObject printRequest = printRequestQueue.take();
+                    Platform.runLater(                                             
+                        new Runnable() {                                           
+                            @Override public void run() {                          
+                                handlePrint(printRequest);
+                            }                                                      
+                        }                                                          
+                    ); 
+                } catch (InterruptedException ie) {
+                }
+            }
+        }
+    }
+
+    /** Add a print request object to the print queue. */
+    public static void enqueuePrintRequest(JSONObject request) {
+        printRequestQueue.offer(request);
+    }
+
+    /**
      * JavaFX startup call
      */
     @Override
     public void start(Stage primaryStage) {
         this.primaryStage = primaryStage;
+        new PrintRequestShuffler().start();
     }
 
     /**
      * Build a browser view from the print content, tell the
      * browser to print itself.
      */
-    private void handlePrint(Map<String,Object> params) {
-        String content = (String) params.get("content");
-        String contentType = (String) params.get("contentType");
-
-        if (content == null) {
-            logger.warning("handlePrint() called with no content");
-            return;
-        }
+    private void handlePrint(JSONObject request) {
 
         browser = new BrowserView();
         Scene scene = new Scene(browser);
@@ -92,21 +119,32 @@ public class Hatch extends Application {
         browser.webEngine.getLoadWorker()
             .stateProperty()
             .addListener( (ChangeListener<State>) (obsValue, oldState, newState) -> {
-                logger.info("browser load state " + newState);
+                logger.finest("browser load state " + newState);
                 if (newState == State.SUCCEEDED) {
-                    logger.info("Print browser page load completed");
+                    logger.finer("Print browser page load completed");
 
-                    // Avoid nested UI event loops -- runLater
+                    // Avoid nested UI event loops
                     Platform.runLater(new Runnable() {
                         @Override public void run() {
-                            new PrintManager().print(browser.webEngine, params);
+                            new PrintManager().print(browser.webEngine, request);
                         }
                     });
                 }
             });
 
-        logger.info("printing " + content.length() + " bytes of " + contentType);
-        browser.webEngine.loadContent(content, contentType);
+        try {
+            String content = request.getString("content");
+            String contentType = request.getString("contentType");
+    
+            logger.info("printing " + 
+                content.length() + " bytes of " + contentType);
+
+            browser.webEngine.loadContent(content, contentType);
+
+        } catch (JSONException je) {
+            // RequestHandler already confirmed 'content' and 'contentType'
+            // values exist.  No exceptions should occur here.
+        }
     }
 
     /* TODO: make me configurable via config file
index d6f7e71..c82baeb 100644 (file)
@@ -15,7 +15,6 @@
  */
 package org.evergreen_ils.hatch;
 
-
 // printing
 import javafx.print.*;
 import javafx.scene.web.WebEngine;
@@ -33,18 +32,20 @@ import javax.print.attribute.standard.OrientationRequested;
 import java.lang.IllegalArgumentException;
 
 // data structures
+import java.util.Set;
 import java.util.Map;
 import java.util.List;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
-import java.util.Set;
-import java.util.LinkedHashSet;
+
+import java.util.logging.Logger;
+
+import org.json.*;
 
 public class PrintManager {
 
     /** Our logger instance */
-    //static final Logger logger = Log.getLogger("PrintManager");
+    static final Logger logger = Hatch.getLogger();
 
     /**
      * Shows the print dialog, allowing the user to modify settings,
@@ -85,8 +86,15 @@ public class PrintManager {
      * @param engine The WebEngine instance to print
      * @param params Print request parameters
      */
-    public void print(WebEngine engine, Map<String,Object>params) {
+    public void print(WebEngine engine, JSONObject request) {
+
+        JSONObject response = new JSONObject();
+
+        try {
+            long msgid = request.getLong("msgid");
+            response.put("msgid", msgid);
 
+        /*
         Long msgid = (Long) params.get("msgid");
         Boolean showDialog = (Boolean) params.get("showDialog");
 
@@ -94,10 +102,6 @@ public class PrintManager {
         Map<String,Object> settings = 
             (Map<String,Object>) params.get("config");
 
-        /*
-        HatchWebSocketHandler socket = 
-            (HatchWebSocketHandler) params.get("socket");
-            */
 
         PrinterJob job = null;
 
@@ -122,17 +126,23 @@ public class PrintManager {
             //logger.info("No print dialog requested");
         }
 
-        Thread[] all = new Thread[100];
-        int count = Thread.currentThread().enumerate(all);
-        //logger.info(count + " active threads in print");
-        //logger.info("Thread " + Thread.currentThread().getId() + " printing...");
-
         engine.print(job);
-        //logger.info("after print");
 
         job.endJob();
 
         //socket.reply("Print job succeeded", msgid);
+        
+        */
+
+        } catch (JSONException je) {
+            String error = "JSON request protocol error: " 
+                + je.toString() + " : " + request.toString();
+
+            logger.warning(error);
+            response.put("error", error);
+        }
+
+        RequestHandler.reply(response);
     }
 
     /**
index d3d1221..f74b137 100644 (file)
@@ -8,13 +8,9 @@ import java.util.logging.*;
  * via MessageIO.
  */
 public class RequestHandler extends Thread {
-    private MessageIO io;
+    private static MessageIO io = new MessageIO();
     static final Logger logger = Hatch.getLogger();
 
-    public RequestHandler() {
-        io = new MessageIO();
-    }
-
     /**
      * Unpack a JSON request and send it to the necessary Hatch handler.
      */
@@ -43,15 +39,25 @@ public class RequestHandler extends Thread {
             case "print":
                 String content = request.getString("content");
                 String contentType = request.getString("contentType");
-                
+                Hatch.enqueuePrintRequest(request);
+                // print response is delivered from the FX print
+                // thread via reply().
+                return;    
 
             default:
                 response.put("error", "Unknown action: " + action);
         }
 
-        io.sendMessage(response);
+        reply(response);
     }
 
+    /**
+     * Most replies are delivered from within dispatchRequest, but some
+     * like printing require the reply be delivered from another thread.
+     */
+    protected static void reply(JSONObject response) {
+        io.sendMessage(response);
+    }
 
     public void run() {