2014-10-07 59 views
2

我正在寻找一种方法,可以从独立的基于Swing的客户端(JDK7-SE)同时连接到Glassfish 4+(JDK7-EE)的多个实例。我顺利地通过以下方式连接到一个实例:如何同时远程连接到多个Glassfish 4+实例?

这是初始上下文的建设:

context.lookup("java:global/LawSuiteEE/LawSuiteEE-ejb/GlobalsFacade!ch.lawsuite.control.GlobalsFacadeRemote"); 

private void connect(String address, String port) { 
    System.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory"); 
    System.setProperty("com.sun.corba.ee.transport.ORBTCPTimeouts", "500:30000:20:"+Integer.MAX_VALUE); 
    System.setProperty("com.sun.corba.ee.transport.ORBTCPConnectTimeouts", "250:90000:100:"+Integer.MAX_VALUE); 
    System.setProperty("com.sun.corba.ee.transport.ORBWaitForResponseTimeout", "300000"); 
    System.setProperty("java.security.auth.login.config", new File("login.conf").getAbsolutePath()); 
    System.setProperty("org.omg.CORBA.ORBInitialHost", address); 
    System.setProperty("org.omg.CORBA.ORBInitialPort", port); 
    InitialContext context = new InitialContext(); 
} 

看企业都在通过JNDI使用远程接口完成我正在使用驻留在服务器上的自定义JDBC域,并且正常工作。在客户端我通过以下login.conf的初始上下文(见上面的代码):

default { 
    com.sun.enterprise.security.auth.login.ClientPasswordLoginModule required debug=true; 
}; 

验证目前通过ProgrammaticLogin完成:

private void login(String username, char[] password) { 
    ProgrammaticLogin plogin = new ProgrammaticLogin(); 
    plogin.login(username, password); 
} 

所有这一切工作正常!但是,在独立客户端启动期间,我想同时连接到位于不同服务器上的另一个EJB。

由于ProgrammaticLogin与初始上下文没有直接关系,我不确定如何以不同的凭据(例如用户名/密码)同时登录到两个不同的Glassfish服务器?有人有任何想法?

+0

您的问题说你想连接到多个服务器,但你的赏金声明说你正在寻找连接到EJB:有区别。你真的在找什么? – kolossus 2014-10-12 17:53:39

+0

我在不同的服务器上部署了不同的EJB。我想同时从独立的Java SE客户端连接到两个服务器/ EJB。通过连接Glassfish,我的意思是通过JNDI查找在该服务器上访问EJB。 – salocinx 2014-10-13 06:39:00

+0

EJB是安全的,所以我需要一个可以在服务器上进行身份验证的地方(正在使用我的自定义JDBC领域)。但只要JVM正在运行,它就只能与一台服务器一起工作,因为属性被设置为JVM(System.setProperty(x,y))。 – salocinx 2014-10-13 06:41:56

回答

1

对此问题的进一步检查发现,初始上下文只能在每个JVM基础上设置一次。因此,只要通过使用System.setProperty(String,String)设置ORB并初始化初始上下文对象,SerialInitContextFactory的设计就让您不再更改选定的端点。

因此,我决定将不同的JVM连接到不同的Glassfish服务器。最后,我最终得到了一个单独的项目,该项目管理与应用程序服务器的连接,并由RMI与主项目进行通信。

目前我的项目由两个不同的EE项目组成,我想同时连接两个项目,即“LawSuiteEE”和“MgmtCenterEE”。下面是处理连接的新项目:

public static void main(String args[]) { 
    try { 
     if(args.length==2) { 
      if(args[1].equals("LawSuiteEE")) { 
       ILawSuiteEE stub = (ILawSuiteEE) UnicastRemoteObject.exportObject(new LawSuiteEE(), 0); 
       Registry registry = LocateRegistry.createRegistry(Integer.parseInt(args[0])); 
       registry.bind("LawSuiteEE", stub); 
      } else if(args[1].equals("MgmtCenterEE")) { 
       ILawSuiteEE stub = (ILawSuiteEE) UnicastRemoteObject.exportObject(new MgmtCenterEE(), 0); 
       Registry registry = LocateRegistry.createRegistry(Integer.parseInt(args[0])); 
       registry.bind("MgmtCenterEE", stub); 
      } else { 
       throw new NumberFormatException(); 
      } 
      Logger.getLogger(RemoteContext.class.getName()).log(Level.INFO, "Remote context service is listening on port "+args[0]+" for incoming requests delegating to "+args[1]+"."); 
      System.out.println("SIGNAL[READY]"); 
     } else { 
      throw new NumberFormatException(); 
     } 
    } catch (RemoteException ex) { 
     System.exit(1); 
    } catch (AlreadyBoundException ex) { 
     System.exit(2); 
    } catch(NumberFormatException ex) { 
     System.exit(3); 
    } 

接口ILawSuiteEE用于RMI这与主体工程之间(第二接口IMgmtCenterEE是完全一样的):

public interface ILawSuiteEE extends IConcurrentDatastore { 

    void connect(String address, String port) throws RemoteException; 

    void disconnect() throws RemoteException; 

    boolean login(String username, char[] password) throws RemoteException; 

} 

相应的执行:

public class LawSuiteEE implements ILawSuiteEE { 

private InitialContext context; 
private ProgrammaticLogin login; 


@Override 
public void connect(String address, String port) throws RemoteException { 
    if(context==null) { 
     try { 
      System.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory"); 
      System.setProperty("com.sun.corba.ee.transport.ORBTCPTimeouts", "500:30000:20:"+Integer.MAX_VALUE); 
      System.setProperty("com.sun.corba.ee.transport.ORBTCPConnectTimeouts", "250:90000:100:"+Integer.MAX_VALUE); 
      System.setProperty("com.sun.corba.ee.transport.ORBWaitForResponseTimeout", "300000"); 
      System.setProperty("java.security.auth.login.config", new File("login.conf").getAbsolutePath()); 
      System.setProperty("org.omg.CORBA.ORBInitialHost", address); 
      System.setProperty("org.omg.CORBA.ORBInitialPort", Integer.toString(port)); 
      Logger.getLogger(RemoteDatastore.class.getName()).log(Level.INFO, "Try to connect to application server at "+System.getProperty("org.omg.CORBA.ORBInitialHost")+":"+System.getProperty("org.omg.CORBA.ORBInitialPort")+" ...");    
      context = new InitialContext(); 
     } catch (NamingException ex) { 
      throw new RemoteException(ex.getMessage()); 
     } 
    } 
} 

@Override 
public void disconnect() throws RemoteException { 
    if(context!=null) { 
     try { 
      context.close(); 
      Logger.getLogger(LawSuiteEE.class.getName()).log(Level.INFO, "Server context successfully closed."); 
     } catch (NamingException ex) { 
      Logger.getLogger(LawSuiteEE.class.getName()).log(Level.SEVERE, "Couldn't close server context."); 
     } finally { 
      this.facades.clear(); 
      this.services.clear(); 
      this.context=null; 
     } 
    } 
} 

@Override 
public boolean login(String username, char[] password) throws RemoteException { 
    login = new ProgrammaticLogin(); 
    return login.login(username, password); 
} 

}

在主亲ject我要与以下连接:

public class LawSuiteDatastore extends Thread implements ILawSuiteEE { 

    private int port; 
    private int trials; 
    private boolean ready; 
    private Process process; 
    private ILawSuiteEE stub; 

    public LawSuiteDatastore() { 
     this.setName("K+: Remote-Datastore-Connection"); 
     this.port = RemoteDatastoreService.cport++; 
    } 

    @Override 
    public void run() { 
     try { 
      Tools.log(RemoteDatastoreService.class, Level.INFO, "Starting RMI registry on port "+port+" for connecting to LawSuiteEE server instance."); 
      this.process = Runtime.getRuntime().exec(new String[] {"java", "-jar", Context.getWorkingDirectory()+"/lib/LawSuiteSX.jar", Integer.toString(port), "LawSuiteEE"}); 
      //<editor-fold defaultstate="collapsed" desc="Redirect Error Stream"> 
      new Thread(new Runnable() { 
       @Override 
       public void run() { 
        try{ 
         try(DataInputStream in = new DataInputStream(process.getErrorStream())) { 
          BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
          String line; 
          while((line=br.readLine())!=null) { 
           Tools.log(RemoteDatastoreService.class, Level.SEVERE, line); 
          } 
         } 
        } catch(Exception ex){ 
         Tools.log(MgmtCenterDatastore.class, Level.SEVERE, ex.getMessage()); 
        } 
       } 
      }).start(); 
      //</editor-fold> 
      //<editor-fold defaultstate="collapsed" desc="Redirect Output Stream"> 
      new Thread(new Runnable() { 
       @Override 
       public void run() { 
        try{ 
         try(DataInputStream in = new DataInputStream(process.getInputStream())) { 
          BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
          String line; 
          while((line=br.readLine())!=null) { 
           if(line.contains("SIGNAL[READY]")) { ready=true; } 
           Tools.log(RemoteDatastoreService.class, Level.INFO, line); 
          } 
         } 
        } catch(Exception ex){ 
         Tools.log(MgmtCenterDatastore.class, Level.SEVERE, ex.getMessage()); 
        } 
       } 
      }).start(); 
      //</editor-fold> 
      // keep thread alive as long process is alive 
      if(process.waitFor()>0) { 
       // port was already bound 
       if(process.exitValue()==2) { 
        // try it with a different port and start over again 
        if(trials<3) { 
         process = null; 
         port = ++RemoteDatastoreService.cport; 
         trials++; 
         if(trials<3) { 
          start(); 
         } 
        } 
       } 
      } 
     } catch (IOException ex) { 
      Tools.log(RemoteDatastoreService.class, Level.SEVERE, ex.getMessage()); 
     } catch (InterruptedException ex) { 
      Tools.log(RemoteDatastoreService.class, Level.SEVERE, ex.getMessage()); 
     } 
    } 

    public boolean isReady() { 
     return ready; 
    } 

    public int getTrials() { 
     return trials; 
    } 

    @Override 
    public void connect(RemoteDatastore datastore) throws RemoteException { 
     try { 
      Tools.log(RemoteDatastoreService.class, Level.INFO, "Locating RMI registry on port "+port+" for connecting to LawSuiteEE server instance."); 
      Registry registry = LocateRegistry.getRegistry(port); 
      stub = (ILawSuiteEE)registry.lookup("LawSuiteEE"); 
      stub.connect(datastore); 
     } catch (NotBoundException ex) { 
      Logger.getLogger(RemoteDatastoreService.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    @Override 
    public void disconnect() throws RemoteException { 
     if(process!=null && stub!=null) { 
      stub.disconnect(); 
      process.destroy(); 
     } else { 
      throw new RemoteException("Remote RMI server is not ready."); 
     } 
    } 

    @Override 
    public boolean login(String username, char[] password) throws RemoteException { 
     if(process!=null && stub!=null) { 
      return stub.login(username, password); 
     } else { 
      throw new RemoteException("Remote RMI server is not ready."); 
     } 
    } 

} 
0

如何使用多个线程,每个服务器一个? 您可以为每个需要的连接创建一个新线程,在每个线程上设置InitialContext,并使用不同的凭证连接到ProgrammaticLogin。

您可以通过实现Runnable接口来创建自己的“自定义”线程,并为其创建一个接收证书和/或InitialContext对象的构造函数。 简单的例子:

public class MyThread implements Runnable { 
    private ProgrammaticLogin plogin; 
    private string user; 
    private char[] pass; 

    public MyThread(String username, char[] password,InitialContext context) { 
      this.user = username; 
      this.pass = password; 
      this.plogin = new ProgrammaticLogin(); 

      //add more code here if needed 
     } 

     public void run() { 
      //insert code here when thread will run 
     } 
     } 

,因此调用它:

Runnable thread1 = new MyThread("my user1","my pass1",ContextObject1); 
Runnable thread2 = new MyThread("my user2","my pass2",ContextObject2); 

new Thread(thread1).start(); 
new Thread(thread2).start(); 

当然,这是一个非常简单的例子,它可能不适合您的具体需求,但我认为这是一个良好的开端为你所需要的。由于每个Context和登录凭证将在不同的线程上运行,因此它们将拥有自己的独立执行堆栈,并且不应该遇到任何并发问题(两个线程访问同一个对象)。 但是,你应该对并发和线程有一个很好的理解,否则你可能遇到不同的异常,由于使用多线程而难以调试。

汤姆。