我在这里阅读了以下博客文章, Reconnect RMI client after server restart
它声明当属性refreshStubOnConnectFailure设置为true时,我的客户端RMI将尝试重新连接到服务器。所以我在将更改添加到系统之前编写了以下代码来测试它。我启动了我的服务器,然后是这个测试程序。在服务器和客户端正在谈论的一些消息后,我停止了服务器。我得到了一个异常跟踪,但没有输入任何catch块。像往常一样,我很困惑,因为我认为至少有一个我的catch块会被执行。我的程序输出如下。
Main starting
Hi There Received
Hi There Received
Hi There Received
Jan 05, 2016 9:32:06 PM org.springframework.remoting.rmi.RmiProxyFactoryBean handleRemoteConnectFailure
WARNING: Could not connect to RMI service [rmi://127.0.0.1:1099/Ping] - retrying
Exception in thread "main" org.springframework.remoting.RemoteLookupFailureException: Lookup of RMI stub failed; nested exception is java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused
at org.springframework.remoting.rmi.RmiClientInterceptor.lookupStub(RmiClientInterceptor.java:215)
at org.springframework.remoting.rmi.RmiClientInterceptor.refreshAndRetry(RmiClientInterceptor.java:326)
at org.springframework.remoting.rmi.RmiClientInterceptor.handleRemoteConnectFailure(RmiClientInterceptor.java:307)
at org.springframework.remoting.rmi.RmiClientInterceptor.invoke(RmiClientInterceptor.java:267)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy1.sayHello(Unknown Source)
at com.edvs.main.TestIt.main(TestIt.java:34)
Caused by: java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:342)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at java.rmi.Naming.lookup(Naming.java:101)
at org.springframework.remoting.rmi.RmiClientInterceptor.lookupStub(RmiClientInterceptor.java:200)
... 7 more
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:148)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
... 13 more
我的代码如下:
package com.edvs.main;
import java.rmi.ConnectException;
import java.rmi.RemoteException
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.edvs.service.PingService;
public class TestIt {
public static void main(String[] args) {
String file = "bean.xml";
ApplicationContext context = null;
try {
context = new ClassPathXmlApplicationContext(file);
} catch (Exception e) {
System.out.println("exception:" + e.getMessage());
System.exit(99);
}
System.out.println("Main starting");
PingService ps = (PingService) context.getBean("pingBean");
boolean done = false;
int count = 30;
if (ps != null) {
while (!done && count > 0) {
try {
if (ps.sayHello("Annapolis").equals("hi there")) {
System.out.println("Hi There Received");
}
} catch (ConnectException ce) {
System.out.println("ConnectionException");
/*
* Something happened with the server so see if it is
* something we should retry the connection.
*/
if (ce.getMessage().contains("Connection refused")) {
System.out.println("Connection Refused");
}
} catch (RemoteException e) {
System.out.println("RemoteException:" + e.getMessage());
}
count--;
try {
Thread.yield();
Thread.sleep(3000);
} catch (InterruptedException e) {
done = true;
}
}
}
((ConfigurableApplicationContext) context).close();
System.out.println("Test has ended.");
}
}
bean.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">
<bean id="pingBean" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://127.0.0.1:1099/Ping" />
<property name="serviceInterface" value="com.edvs.service.PingService" />
<property name="refreshStubOnConnectFailure" value="true" />
<property name="lookupStubOnStartup" value="false" />
</bean>
没有抓住任何例外情况。应用程序刚刚终止。如果我注释掉refreshStubOnConnectFailure,则抛出ConnectionException异常,但我不知道重启服务器后如何重新启动连接。
为了完整性和其他人注视,我正在添加我的最终测试代码。它最初测试服务器,然后继续与服务器通信。
package com.edvs.main;
import java.net.MalformedURLException;
import java.rmi.ConnectException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
import com.edvs.service.PingService;
public class TestIt {
static Log log = LogFactory.getLog(TestIt.class.getName());
public static void main(String[] args) {
String file = "bean.xml";
ApplicationContext context = null;
try {
context = new ClassPathXmlApplicationContext(file);
} catch (Exception e) {
System.out.println("exception:" + e.getMessage());
System.exit(99);
}
System.out.println("Main starting");
log.info("foo");
boolean done = false;
int count = 30;
RmiProxyFactoryBean rpfb = (RmiProxyFactoryBean) context.getBean("&pingBean");
String serviceUrl = rpfb.getServiceUrl();
/*
* See if the server is there as we startup.
*/
while (true) {
if (null != isServerThere(serviceUrl)) {
/*
* The server is there so continue with our processing.
*/
break;
} else {
/*
* The server is not there so sleep and then try again.
*/
try {
Thread.yield();
Thread.sleep(3000);
} catch (InterruptedException e) {
System.exit(33);
}
}
}
PingService ps = (PingService) context.getBean("pingBean");
try {
log.info("Service Name:" + ps.getServiceName());
log.info("all:" + ps.toString());
log.info("serviceUrl:" + rpfb.getServiceUrl());
} catch (RemoteException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (!done && count > 0) {
try {
if (ps.sayHello("Annapolis").equals("hi there")) {
log.info("Hi There Received");
}
} catch (ConnectException ce) {
log.info("ConnectionException");
/*
* Something happened with the server so see if it is something we
* should retry the connection.
*/
if (ce.getMessage().contains("Connection refused")) {
log.info("Connection Refused");
ps = (PingService) isServerThere(serviceUrl);
}
} catch (RemoteException e) {
System.out.println("RemoteException:" + e.getMessage());
}
count--;
try {
Thread.yield();
Thread.sleep(3000);
} catch (InterruptedException e) {
done = true;
}
}
((ConfigurableApplicationContext) context).close();
System.out.println("Test has ended.");
}
static private Remote isServerThere(String serviceUrl) {
Remote remote = null;
try {
remote = Naming.lookup(serviceUrl);
} catch (MalformedURLException | RemoteException | NotBoundException e) {
log.error("Exception:" + e.getMessage());
}
return remote;
}
}
答案 0 :(得分:0)
您正在向注册管理机构<{1}} 获取。由于Regsitry没有运行,因此无需重新查找就可以解决这个问题。这就是你需要解决的问题。
当您获得拒绝连接到远程对象时,您设置的属性将生效。
答案 1 :(得分:0)
我想我在这个论坛中找到了一个提到Naming.lookup()的答案。我更改了用于ConnectionException的catch块中的代码。该代码现在如下所示。
if (ce.getMessage().contains("Connection refused")) {
log.info("Connection Refused");
try {
ps = (PingService)Naming.lookup("rmi://127.0.0.1:1099/Ping");
} catch (MalformedURLException | RemoteException | NotBoundException e) {
log.info("Naming Exception:" + e.getMessage());
}
}
Naming.lookup()将继续失败,直到服务器进入备份。重新启动服务器后,将检索新的PingService对象,然后可以使用该对象。我认为这是正确的,并会感谢论坛的评论。