Remote EJB Client Channel Closed Errors
jfisherdev May 16, 2017 2:16 PMWe have been encountering the exception below seemingly at random.
java.rmi.RemoteException: Error; nested exception is: java.io.IOException: Channel Channel ID d1a61663 (outbound) of Remoting connection 20b68fcb to $hostname$/$hostIp$:$http.port$ has been closed //Invoke Remote EJB interface here Caused by: java.rmi.RemoteException: Error; nested exception is: java.io.IOException: Channel Channel ID d1a61663 (outbound) of Remoting connection 20b68fcb to $hostname$/$hostIp$:$http.port$ has been closed at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:236) at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183) at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146) at com.sun.proxy.$Proxy2.invoke(Unknown Source) at sun.reflect.GeneratedMethodAccessor9.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) ... 10 more Caused by: java.io.IOException: Channel Channel ID d1a61663 (outbound) of Remoting connection 20b68fcb to $hostname$/$hostIp$:$http.port$ has been closed at org.jboss.ejb.client.remoting.ChannelAssociation$1.handleClose(ChannelAssociation.java:123) at org.jboss.ejb.client.remoting.ChannelAssociation$1.handleClose(ChannelAssociation.java:115) at org.jboss.remoting3.spi.SpiUtils.safeHandleClose(SpiUtils.java:54) at org.jboss.remoting3.spi.AbstractHandleableCloseable$CloseHandlerTask.run(AbstractHandleableCloseable.java:514) at org.jboss.remoting3.spi.AbstractHandleableCloseable.runCloseTask(AbstractHandleableCloseable.java:419) at org.jboss.remoting3.spi.AbstractHandleableCloseable.closeComplete(AbstractHandleableCloseable.java:290) at org.jboss.remoting3.remote.RemoteConnectionChannel.closeAction(RemoteConnectionChannel.java:543) at org.jboss.remoting3.spi.AbstractHandleableCloseable.closeAsync(AbstractHandleableCloseable.java:372) at org.jboss.remoting3.remote.RemoteConnectionHandler.closeAllChannels(RemoteConnectionHandler.java:429) at org.jboss.remoting3.remote.RemoteConnectionHandler.sendCloseRequest(RemoteConnectionHandler.java:233) at org.jboss.remoting3.remote.RemoteConnectionHandler.handleConnectionClose(RemoteConnectionHandler.java:113) at org.jboss.remoting3.remote.RemoteReadListener$1$1.run(RemoteReadListener.java:56) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
The call is being made from a remote standalone EJB client [a Swing GUI application] to a standalone WildFly 9.0.2.final server.
An approximation of the classes we use to facilitate making the remote invocation as well as the call itself are as follows.
//Wraps a Context object to simplify the lookup
public class EjbClient implements AutoCloseable {
private final Context context;
public EjbClient(Context context) {
this.context = context;
}
//Other lookup helper operations
public Object lookupEJB(String jndiName) throws NamingException {
return context.lookup(jndiName);
}
@Override//from AutoCloseable
public void close() throws Exception {
context.close();
}
}
//Singleton object that maintains EjbClient instances for the lifetime of the application
public EjbClientFactory {
public static EjbClientFactory getInstance(){
...
}
//Default client/context for this application
private EjbClient defaultClient;
//EjbClients/contexts for this client to communicate with other applications/servers
private final Map<String, EjbClient> otherAppClients = new ConcurrentHashMap<>();
public EjbClient getDefaultClient() throws NamingException {
if(defaultClient == null) {
defaultClient = new InitialContext(createProperties());
}
return defaultClient;
}
public EjbClient getClientForApp(String app) {
if(otherAppClients.containsKey(app){
return otherAppClients.get(app);
}
final Properties appClientProperties = createProperties();
//Add/adjust app-specific properties as needed
final EjbClient appClient = new EjbClient(new InitialContext(appClientProperties));
otherAppClients.put(app, appClient);
return appClient;
}
private Properties createProperties() {
//Create properties for scoped EJB client context, relevant properties given below:
//java.naming.factory.url.pkgs = org.jboss.ejb.client.naming
//connect.options.org.jboss.remoting3.RemotingOptions.HEARTBEAT_INTERVAL = 60000
//channel.options.org.jboss.remoting3.RemotingOptions.MAX_INBOUND_MESSAGES = 80
//channel.options.org.jboss.remoting3.RemotingOptions.MAX_OUTBOUND_MESSAGES = 80
//org.jboss.ejb.clint.scoped.context = true
}
}
//The Swing client that makes the remote EJB calls.
public class AppGuiClient {
private Runnable updateAlertsRunnable = new Runnable() {
@Override
public void run() {
updateAlerts();
}
}
void refresh() {
//The < Java 5 way of doing the fetch on a separate thread was already there and not my idea
final Thread updateAlertsThread = new Thread(updateAlertsRunnable);
updateAlertsThread.setDaemon(true);
updateAlertsThread.start();
}
private void updateAlerts() {
try {
final EjbClient ejbClient = EjbClientFactory.getInstance().getDefaultClient();
//Stateless session bean remote interface
final AlertSessionRemote remote = (AlertSessionRemote) ejbClient.lookup(...);
//JNDI lookup is fine, it SOMETIMES fails here when invoking the remote proxy
final List<Alert> alerts = remote.getAlerts();
//Update GUI with alert information
addAlerts(alerts);
} catch (Exception e) {
//Show a dialog with exception details, the same happens for uncaught exceptions
displayException(e);
}
}
}
I don't understand how this state and exception are being reached and that this only occurs sometimes with this method. The client context is not closed between invocations [not closed until the application is finished with them], which would make sense, but isn't the case here. Also, subsequent calls with the same client/context work, which makes this more confusing.
Is there client or server-side configuration that might be a problem? The only areas I could think of on the server-side would be XNIO or remoting.
Any information or ideas about this would be appreciated greatly.