java.util.concurrent.ExecutionException during sending http POST request

  • Platform information:
    • OS: Ubuntu
    • openHAB version: 2.3.0

Hi. I have a rule for getting status of my HA device.

I need to send register request first, and then request for getting info.

Working ok, but sometimes I get java.util.concurrent.ExecutionException with unknown reason. Also I can’t catch this exception usng try-catch.

Anybody can help me to find whats wrong with this rule?

2018-06-14 09:58:50.277 [ERROR] [.smarthome.model.script.actions.HTTP] - Fatal transport error: java.util.concurrent.ExecutionException: org.eclipse.jetty.io.EofException
2018-06-14 09:58:51.102 [ERROR] [.smarthome.model.script.actions.HTTP] - Fatal transport error: java.util.concurrent.ExecutionException: java.io.EOFException: HttpConnectionOverHTTP@af0fba(l:/192.168.1.169:49594 <-> r:/192.168.1.116:8181,closed=false)[HttpChannelOverHTTP@16863eb(exchange=HttpExchange@1b981d4 req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@19f060(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@f7ea06{s=START}],recv=HttpReceiverOverHTTP@dab648(rsp=IDLE,failure=null)[HttpParser{s=CLOSED,0 of -1}]]]

And my rule…

rule "Get panel state"
when
	Time cron '0 0/1 * 1/1 * ? *'
then
    try {
        var reg_url = "http://192.168.1.116:8181/remote/json-rpc"
        var contenttype = "application/json"
        var POSTrequest = '{"params": ["192.168.1.169", 1818, "user"],"jsonrpc": "2.0","method":"PmaxService/registerClient", "id":11}'
        sendHttpPostRequest(reg_url, contenttype, POSTrequest)

        var url = "http://192.168.1.116:8181/remote/json-rpc"
        contenttype = "application/json"
        POSTrequest = '{"params": [ 1 ],"jsonrpc":"2.0","method":"PmaxService/getPanelState", "id":11}'
        var output = sendHttpPostRequest(url, contenttype, POSTrequest)
        
        val String status = transform("JSONPATH", "$.result.state", output)
        
        logInfo("received_status", status)

        if(status == 'DISARM') {
            postUpdate(System_ARMED_API, status)
        }
        else if (status == 'HOME'){
            postUpdate(System_ARMED_API, status)
        }
        else if (status == 'AWAY'){
            postUpdate(System_ARMED_API, status)
        }
        else {
            return
        }
    } catch(Exception e) {
        logError("received_status", "exception" + e.getMessage)
    }
end
rule "Get panel state"
when
	Time cron '0 0/1 * 1/1 * ? *'
then
    try {
        var reg_url = "http://192.168.1.116:8181/remote/json-rpc"
        var contenttype = "application/json"
        var POSTrequest = '{"params": ["192.168.1.169", 1818, "user"],"jsonrpc": "2.0","method":"PmaxService/registerClient", "id":11}'
        sendHttpPostRequest(reg_url, contenttype, POSTrequest)
        logInfo("RULE",output)

        // var url = "http://192.168.1.116:8181/remote/json-rpc"
        // contenttype = "application/json"
        POSTrequest = '{"params": [ 1 ],"jsonrpc":"2.0","method":"PmaxService/getPanelState", "id":11}'
        var output = sendHttpPostRequest(url, contenttype, POSTrequest)
        
        val String status = transform("JSONPATH", "$.result.state", output)
        
        logInfo("received_status", status)

        if(status == 'DISARM') {
            postUpdate(System_ARMED_API, status)
        }
        else if (status == 'HOME'){
            postUpdate(System_ARMED_API, status)
        }
        else if (status == 'AWAY'){
            postUpdate(System_ARMED_API, status)
        }
        else {
            return
        }
    } catch(Exception e) {
        logError("received_status", "exception" + e.getMessage)
    }
end

You sent only first request, which does not return status data. In this case transformation fails
val String status = transform("JSONPATH", "$.result.state", output)

Again - need to send 2 requests one by one: register and get data

An EOF exception is almost always caused by the remote end closing the connection before all of the expected data has been received. Are there any logs or other information available on the remote end that might show you a little more info?

What happens if you put in a Thread::sleep between the two requests so the remote end gets a little time between requests? I wouldn’t expect it to need more than 500 msec if this works most of the time.

You probably can’t catch this exception because it looks like it is caught in the HTTP Action itself.

1 Like

Thank you for your really helpful answer. Just adding sleep 500 ms improoved more stability. Now I’m testing with 1000 ms.

Also, thank you for pointing out the root of the problem. Need to investigate how to get logs from another side and check it.

I’m not sure about this, but if you save the response from the first POST to a variable the rule would have to wait for the operation to finish before moving on to the next step.

var dummy = sendHttpPostRequest(reg_url, contenttype, POSTrequest)

You will get a warning in the logs that the variable is never used, but it’s safe to ignore. You can always log the variable in a logInfo statement to get rid of the warning and improve debugging of the rule.

1 Like

If you don’t mind silencing all http request errors you could add this to the org.ops4j.pax.logging.cfg:

log4j2.logger.http.name = org.eclipse.smarthome.model.script.actions.HTTP
log4j2.logger.http.level = OFF