Use Older "remoting" Protocol Instead of "http-remoting" with "http-upgrade" in JBoss EAP 7

Solution Verified - Updated

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 7
  • Remote-invoked / client-server / server-to-server Enterprise Java Beans (EJB), potentially with EJB hosted on JBoss EAP 6
  • Remoting protocol

Issue

  • Configure remote protocol
  • Call Remote EJB on old version of JBoss EAP
  • Remote invokation fails with

      TRACE [org.jboss.remoting.remote.connection] (default I/O-59) Connection error detail: java.io.IOException: XNIO000804: Received an invalid message length of 369296128
              at org.xnio.channels.FramedMessageChannel.receive(FramedMessageChannel.java:108)
              at org.jboss.remoting3.remote.ServerConnectionOpenListener$Initial.handleEvent(ServerConnectionOpenListener.java:228)
              at org.jboss.remoting3.remote.ServerConnectionOpenListener$Initial.handleEvent(ServerConnectionOpenListener.java:139)
              at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
              at org.xnio.channels.TranslatingSuspendableChannel.handleReadable(TranslatingSuspendableChannel.java:199)
              at org.xnio.channels.TranslatingSuspendableChannel$1.handleEvent(TranslatingSuspendableChannel.java:113)
              at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
              at org.xnio.ChannelListeners$DelegatingChannelListener.handleEvent(ChannelListeners.java:1092)
              at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
              at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
              at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:88)
              at org.xnio.nio.WorkerThread.run(WorkerThread.java:559)
    
      DEBUG [org.jboss.remoting.remote.connection] (default I/O-59) JBREM000200: Remote connection failed: java.io.IOException: XNIO000804: Received an invalid message length of 369296128
    
  • Our remote-outbound-connection gets error java.io.IOException: Invalid response using configuration:

      <remote-outbound-connection name="remote-ejb-connection" outbound-socket-binding-ref="remote-ejb" username="RemotingUser" security-realm="ejb-security-realm">
    

    Error in log

      ERROR [org.jboss.as.ejb3.invocation] (default task-2) REQ-TRX= SESSION= WFLYEJB0034: EJB Invocation failed on component XXXXXService for method public abstract xx,xx.getMETHOD(java.lang.String): javax.ejb.NoSuchEJBException: EJBCLIENT000079: Unable to discover destination for request for EJB StatelessEJBLocator for "XXX/XXX-ejb/XXXXXService", view is interface XXXX, affinity is None
              at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:567) [jboss-ejb-client-4.0.10.Final-redhat-1.jar:4.0.10.Final-redhat-1]
              at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:503) [jboss-ejb-client-4.0.10.Final-redhat-1.jar:4.0.10.Final-redhat-1]
      ...
              Suppressed: java.io.IOException: Invalid response
                      at org.xnio.http.HttpUpgradeParser.parseVersion(HttpUpgradeParser.java:164)
                      at org.xnio.http.HttpUpgradeParser.parse(HttpUpgradeParser.java:55)
                      at org.xnio.http.HttpUpgrade$HttpUpgradeState$UpgradeResultListener.handleEvent(HttpUpgrade.java:419)
                      at org.xnio.http.HttpUpgrade$HttpUpgradeState.flushUpgradeChannel(HttpUpgrade.java:369)
                      at org.xnio.http.HttpUpgrade$HttpUpgradeState.access$900(HttpUpgrade.java:165)
      ...
                      at org.jboss.ejb.protocol.remote.RemotingEJBDiscoveryProvider.getConnectedIdentityUsingClusterEffective(RemotingEJBDiscoveryProvider.java:311) [jboss-ejb-client-4.0.10.Final-redhat-1.jar:4.0.10.Final-redhat-1]
                      at org.jboss.ejb.protocol.remote.RemotingEJBDiscoveryProvider$DiscoveryAttempt.lambda$connectAndDiscover$0(RemotingEJBDiscoveryProvider.java:384) [jboss-ejb-client-4.0.10.Final-redhat-1.jar:4.0.10.Final-redhat-1]
                      at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.8.0_144]
                      at org.jboss.ejb.protocol.remote.RemotingEJBDiscoveryProvider$DiscoveryAttempt.connectAndDiscover(RemotingEJBDiscoveryProvider.java:384) [jboss-ejb-client-4.0.10.Final-redhat-1.jar:4.0.10.Final-redhat-1]
                      at org.jboss.ejb.protocol.remote.RemotingEJBDiscoveryProvider.discover(RemotingEJBDiscoveryProvider.java:209) [jboss-ejb-client-4.0.10.Final-redhat-1.jar:4.0.10.Final-redhat-1]
                      at org.jboss.ejb.protocol.remote.RemoteEJBDiscoveryConfigurator.lambda$configure$0(RemoteEJBDiscoveryConfigurator.java:42) [jboss-ejb-client-4.0.10.Final-redhat-1.jar:4.0.10.Final-redhat-1]
                      at org.wildfly.discovery.impl.AggregateDiscoveryProvider.discover(AggregateDiscoveryProvider.java:58)
                      at org.wildfly.discovery.Discovery.discover(Discovery.java:100)
    

Resolution

Set both sides of the connection to use the older remoting protocol. If the server, client running on a server, or client is running with JBoss EAP 6 or earlier, the step can be skipped because it will default to the older protocol.

  1. Configure server-side the ejb-server application

     <subsystem xmlns="urn:jboss:domain:remoting:3.0">
         <endpoint/>
         <!-- this is the default http-remoting connector configuration -->
         <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/>
         <!-- this is the native remoting connector, note that you need to add a socket-binding also!  -->
         <connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
     </subsystem>
    
     <socket-binding-group ...>
         ...
         <socket-binding name="remoting" port="4447" />
         ...
     </socket-binding-group>
    
  2. Configure the ejb-client application running in on a JBoss EAP 7 server

    Aside from general configuration for the client like jboss-ejb-client.xml with the references to the outbound connection the configuration profile must configure it and use the correct port and protocol.

    1. Add 'protocol' (protocol="remote") will change the outbound protocol and the socket-binding point to the server socket for remoting (4447) instead of http (8080).

       <subsystem xmlns="urn:jboss:domain:remoting:3.0">
       ...
           <outbound-connections>
               <remote-outbound-connection name="remote-ejb-connection" outbound-socket-binding-ref="remote-socket-ejb" security-realm="ApplicationRealm" protocol="remote">
                   <properties ></properties>
               </remote-outbound-connection>
           </outbound-connections>
       </subsystem>
       ...
       <socket-binding-group ...>
           ...
           <outbound-socket-binding name="remote-socket-ejb">
               <remote-destination host="remotHost" port="4447"/>
           </outbound-socket-binding>
      
    2. Put the following in WEB-INF/jboss-ejb-client.xml for a WAR or META-INF/jboss-ejb-client.xml if the deployment is not a WAR. outbound-connection-ref (outbound-connection-ref="remote-ejb-connection") must be corresponding to the name of <remote-outbound-connection> you defined inside remoting subsystem in the previous step.

       <jboss-ejb-client xmlns="urn:jboss:ejb-client:1.0">
       <client-context>
           <ejb-receivers>
               <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection"/>
           </ejb-receivers>
       </client-context>
       </jboss-ejb-client>
      
  3. Standalone client configuration

    The properties must change the protocol for each server as followed as the default is http-remoting:

     remote.connections=one
     remote.connection.one.host=localhost
     remote.connection.one.port = 4447
     remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
     remote.connection.one.protocol=remote
    

Root Cause

The default for EJB connections for JBoss EAP 7 is the http port which use http2 / http-upgrade to choose the right protocol. This is to minimize the number of open ports for the server. Clients and servers using code from JBoss EAP 7 will use this never http-remoting protocol by default.

The binary remoting protocol, which defaults to port 4447, can still be configured, but it must be done on both ends of the connection.

Connections between JBoss EAP 7 and JBoss EAP 6 are supported, but there have been some issues in certain patch versions and version combinations. Make sure to run the latest patch version of JBoss EAP 6.4 and JBoss EAP 7.

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.