olyjosh olyjosh - 1 month ago 14
Java Question

Show Controlfx MaskerPane before newtwork request/bind Maskerpane to Http request

I will like the ControlFx MaskerPane to be showing while the request is going on. I have this code on a button action to make the network request.

if(mp==null){
mp=new MaskerPane();
stackPane.getChildren().add(mp);
mp.setVisible(false);
}
try {

mp.setVisible(true);
JSONObject verifyKey = new Network().verifyKey(pinF.getText(), phoneF.getText(), mp);
if (verifyKey != null) {
String string = verifyKey.getString("ans");
mp.setVisible(false);
if (string.equals("1")) {
// Thanks for buying

} else {
error.setText("Key already used");
error.setVisible(true);
}
}
} catch (JSONException ex) {
mp.setVisible(false);
Logger.getLogger(Buy.class.getName()).log(Level.SEVERE, null, ex);
}


However the verify method in my Network class looks like

public JSONObject verifyKey(String key, String phone, MaskerPane mp){
this.mp=mp;
String url = "http://theUrl";

String httpcall = httpcall(url, "func","verify","key",key,"phone",phone,"type","eDesk");
try {
return new JSONObject(httpcall);

} catch (JSONException ex) {
Logger.getLogger(Network.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}

public String httpcall(String url,String ...args) {
try {

// String charset = "UTF-8"; // Or in Java 7 and later, use the constant: java.nio.charset.StandardCharsets.UTF_8.name()
String charset = java.nio.charset.StandardCharsets.UTF_8.name();
String formatin = "";
Object values[] = new String[args.length/2];
int valCount =0;
for (int i = 0; i < args.length; i+=2) {
formatin+=args[i]+"=%s&";
values[valCount]=URLEncoder.encode(args[i+1], charset);
valCount++;
}

String query = String.format(formatin,values);
query=query.substring(0, query.length()-1);

//Remember to remove proxy lines before production
//SocketAddress addr = new InetSocketAddress("127.0.0.1", 8080);
//Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);

URLConnection connection = new URL(url).openConnection(proxy);
connection.setDoOutput(true); // Triggers POST.
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);

try (OutputStream output = connection.getOutputStream()) {
output.write(query.getBytes(charset));
}

InputStream response = connection.getInputStream();
//return getStringFromInputStream(response);

} catch (UnsupportedEncodingException ex) {
if(mp!=null)mp.setVisible(false);
Logger.getLogger(Buy.class.getName()).log(Level.SEVERE, null, ex);
}catch (MalformedURLException ex) {
if(mp!=null)mp.setVisible(false);
Logger.getLogger(Buy.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
//if(mp!=null)mp.setVisible(false);
Logger.getLogger(Buy.class.getName()).log(Level.SEVERE, null, ex);
//return "{\"ans\":\"1\"}";//xpectd on success
//return "{\"ans\":\"0\",\"err\":\"1\"}";//xpectd on failure
}
return null;
}


The problem is the maskerpane wont show until the network request is called is complete.

Answer

I found out I need to execute the network operation in another thread. One can use Executor services. These can be found in javafx concurrency package

if (mp == null) {
    mp = new MaskerPane();
    stackPane.getChildren().add(mp);
    mp.setVisible(false);
}
mp.setVisible(true);
Runnable task = () -> {
    try {

        JSONObject verifyKey = new Network().verifyKey(pinF.getText(), phoneF.getText(), mp);
        if (verifyKey != null) {
            String string = verifyKey.getString("ans");

//Updating ui from another thread need you to use Platform.runLatter... So wrapping the below with runLatter to avoid exceptions
            mp.setVisible(false);
            if (string.equals("1")) {
                // Thanks for buying

            } else {
                error.setText("Key already used");
                error.setVisible(true);
            }
        }

        Thread back = new Thread(task);
        back.setPriority(Thread.MAX_PRIORITY);
        back.setDaemon(true);
        back.start();

    } catch (JSONException ex) {
        mp.setVisible(false);
        Logger.getLogger(Buy.class.getName()).log(Level.SEVERE, null, ex);
    }

}
        // Run the task in a background thread
Thread back = new Thread(task);
back.setPriority(Thread.MAX_PRIORITY);
back.setDaemon(true);
back.start();

https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm

Comments