<div dir="ltr">Yes. It is another Undertow server with HTTP 2.0 enabled. I can build a repo with two servers to reproduce the issue if it is necessary. <div><br></div><div>Thanks,</div><div><br></div><div>Steve</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 28, 2017 at 10:43 PM, Stuart Douglas <span dir="ltr">&lt;<a href="mailto:sdouglas@redhat.com" target="_blank">sdouglas@redhat.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">What is the endpoint that you are trying to connect to? Is it another<br>
Undertow server?<br>
<span class="HOEnZb"><font color="#888888"><br>
Stuart<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
On Tue, Aug 29, 2017 at 12:17 PM, Steve Hu &lt;<a href="mailto:stevehu@gmail.com">stevehu@gmail.com</a>&gt; wrote:<br>
&gt; Hi Stuart,<br>
&gt;<br>
&gt; Thanks for the quick reply. I have opened an issue<br>
&gt; <a href="https://issues.jboss.org/browse/UNDERTOW-1170" rel="noreferrer" target="_blank">https://issues.jboss.org/<wbr>browse/UNDERTOW-1170</a><br>
&gt;<br>
&gt; Also, I have tried your workaround with h2c-prior:// but got the following<br>
&gt; error in the callback.<br>
&gt;<br>
&gt; java.nio.channels.<wbr>ClosedChannelException<br>
&gt; at<br>
&gt; io.undertow.protocols.http2.<wbr>Http2Channel.createStream(<wbr>Http2Channel.java:827)<br>
&gt; at<br>
&gt; io.undertow.client.http2.<wbr>Http2ClientConnection.<wbr>sendRequest(<wbr>Http2ClientConnection.java:<wbr>195)<br>
&gt; at<br>
&gt; com.networknt.apic.handler.<wbr>DataGetHandler.handleRequest(<wbr>DataGetHandler.java:57)<br>
&gt;<br>
&gt;<br>
&gt; On Mon, Aug 28, 2017 at 9:50 PM, Stuart Douglas &lt;<a href="mailto:sdouglas@redhat.com">sdouglas@redhat.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; This looks like a bug in the client with regards to how it handles<br>
&gt;&gt; HTTP upgrade. If the second request is added before the initial<br>
&gt;&gt; upgrade request is fully processed you can get this error.<br>
&gt;&gt;<br>
&gt;&gt; If you file a JIRA I will look into it. For now a possible workaround<br>
&gt;&gt; would be to use prior knowledge rather than upgrade (by using a URL of<br>
&gt;&gt; the form h2c-prior://target:p8080/<wbr>whatever).<br>
&gt;&gt;<br>
&gt;&gt; Stuart<br>
&gt;&gt;<br>
&gt;&gt; On Tue, Aug 29, 2017 at 11:25 AM, Steve Hu &lt;<a href="mailto:stevehu@gmail.com">stevehu@gmail.com</a>&gt; wrote:<br>
&gt;&gt; &gt; Hi,<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; I am trying to use UndertowClient to call another service in the current<br>
&gt;&gt; &gt; service handleRequest using HTTP 2.0. If I have concurrent requests to<br>
&gt;&gt; &gt; the<br>
&gt;&gt; &gt; current service, then I will get the following error.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; java.io.IOException: UT001033: Invalid connection state<br>
&gt;&gt; &gt; at<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; io.undertow.client.http.<wbr>HttpClientConnection.<wbr>sendRequest(<wbr>HttpClientConnection.java:336)<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Since HTTP 2.0 connection is multiplex, so I use instance variables for<br>
&gt;&gt; &gt; UndertowClient instance and ClientConnection instance and don&#39;t close<br>
&gt;&gt; &gt; the<br>
&gt;&gt; &gt; connection for each call.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; My question is how many requests can go through the same connection? Is<br>
&gt;&gt; &gt; the<br>
&gt;&gt; &gt; Invalid connection state caused by too many requests in the same<br>
&gt;&gt; &gt; connection?<br>
&gt;&gt; &gt; If yes, I can use a connection pool just like the HTTP 1.1. Also, is it<br>
&gt;&gt; &gt; possible that the server will close the connection if it is idle for a<br>
&gt;&gt; &gt; period of time?<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Here is the handler code for reference.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; public class DataGetHandler implements HttpHandler {<br>
&gt;&gt; &gt;     UndertowClient client = UndertowClient.getInstance();<br>
&gt;&gt; &gt;     ClientConnection connection;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;     @Override<br>
&gt;&gt; &gt;     public void handleRequest(<wbr>HttpServerExchange exchange) throws<br>
&gt;&gt; &gt; Exception<br>
&gt;&gt; &gt; {<br>
&gt;&gt; &gt;         List&lt;String&gt; list = new ArrayList&lt;&gt;();<br>
&gt;&gt; &gt;         final CountDownLatch latch = new CountDownLatch(1);<br>
&gt;&gt; &gt;         if(connection == null) {<br>
&gt;&gt; &gt;             try {<br>
&gt;&gt; &gt;                 connection = client.connect(new URI(apidHost),<br>
&gt;&gt; &gt; Http2Client.WORKER, Http2Client.SSL, Http2Client.POOL, enableHttp2 ?<br>
&gt;&gt; &gt; OptionMap.create(<wbr>UndertowOptions.ENABLE_HTTP2, true):<br>
&gt;&gt; &gt; OptionMap.EMPTY).get();<br>
&gt;&gt; &gt;             } catch (Exception e) {<br>
&gt;&gt; &gt;                 logger.error(&quot;Exeption:&quot;, e);<br>
&gt;&gt; &gt;                 throw new ClientException(e);<br>
&gt;&gt; &gt;             }<br>
&gt;&gt; &gt;         }<br>
&gt;&gt; &gt;         final AtomicReference&lt;<wbr>ClientResponse&gt; reference = new<br>
&gt;&gt; &gt; AtomicReference&lt;&gt;();<br>
&gt;&gt; &gt;         try {<br>
&gt;&gt; &gt;             ClientRequest request = new<br>
&gt;&gt; &gt; ClientRequest().setMethod(<wbr>Methods.GET).setPath(apidPath)<wbr>;<br>
&gt;&gt; &gt;             connection.sendRequest(<wbr>request,<br>
&gt;&gt; &gt; client.createClientCallback(<wbr>reference, latch));<br>
&gt;&gt; &gt;             latch.await();<br>
&gt;&gt; &gt;             int statusCode = reference.get().<wbr>getResponseCode();<br>
&gt;&gt; &gt;             if(statusCode &gt;= 300){<br>
&gt;&gt; &gt;                 throw new Exception(&quot;Failed to call API D: &quot; +<br>
&gt;&gt; &gt; statusCode);<br>
&gt;&gt; &gt;             }<br>
&gt;&gt; &gt;             List&lt;String&gt; apidList =<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Config.getInstance().<wbr>getMapper().readValue(<wbr>reference.get().getAttachment(<wbr>Http2Client.RESPONSE_BODY),<br>
&gt;&gt; &gt;                     new TypeReference&lt;List&lt;String&gt;&gt;(){<wbr>});<br>
&gt;&gt; &gt;             list.addAll(apidList);<br>
&gt;&gt; &gt;         } catch (Exception e) {<br>
&gt;&gt; &gt;             logger.error(&quot;Exception:&quot;, e);<br>
&gt;&gt; &gt;             throw new ClientException(e);<br>
&gt;&gt; &gt;         }<br>
&gt;&gt; &gt;         list.add(&quot;API C: Message 1&quot;);<br>
&gt;&gt; &gt;         list.add(&quot;API C: Message 2&quot;);<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; exchange.getResponseSender().<wbr>send(Config.getInstance().<wbr>getMapper().<wbr>writeValueAsString(list));<br>
&gt;&gt; &gt;     }<br>
&gt;&gt; &gt; }<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; ______________________________<wbr>_________________<br>
&gt;&gt; &gt; undertow-dev mailing list<br>
&gt;&gt; &gt; <a href="mailto:undertow-dev@lists.jboss.org">undertow-dev@lists.jboss.org</a><br>
&gt;&gt; &gt; <a href="https://lists.jboss.org/mailman/listinfo/undertow-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/undertow-dev</a><br>
&gt;<br>
&gt;<br>
</div></div></blockquote></div><br></div>