java - Spring RMI刷新StubOnConnectFailure不工作

标签 java spring rmi

我在这里阅读了以下博客文章, Reconnect RMI client after server restart

它指出,当属性refreshStubOnConnectFailure 设置为true 时,我的客户端RMI 将尝试重新连接到服务器。因此,在将更改放入系统之前,我编写了以下代码来测试它。我启动了我的服务器,然后启动了这个测试程序。在服务器和客户端正在交谈的几条消息之后,我停止了服务器。我收到异常跟踪,但没有输入任何 catch block 。像往常一样,我很困惑,因为我认为至少有一个 catch block 会被执行。我的程序输出如下。

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;
}
}

最佳答案

您收到连接被拒绝到注册表的信息。再多的重新查找也无法解决这个问题,因为注册表没有运行。这就是您需要解决的问题。

当您的远程对象的连接被拒绝时,您设置的属性就会生效。

关于java - Spring RMI刷新StubOnConnectFailure不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34624897/

相关文章:

java - 在 Java EE 应用程序之间进行同步调用的最佳方式

java - Maven bundle plugin - 如何添加主类

Java 函数中的数组赋值

java - Spring 将 Autowired SessionAttribute 注入(inject)到服务层

java - 如何将数据从一个java程序发送到另一个java程序

java - RMI 应用程序在从终端运行时抛出错误,但在 Eclipse 中工作正常

java - Hibernate:如何编写 HQL 来获取没有其标识关系记录的实体的记录

java - 检索 TextView 的名称并在其他类之间共享它们的值

spring - JPA @Entity 内的 Bean 注入(inject)

java - 如何在 AppEngine Standard 中运行的 Spring Boot 中设置上下文路径