對此問題的進一步檢查發現,初始上下文只能在每個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.");
}
}
}
您的問題說你想連接到多個服務器,但你的賞金聲明說你正在尋找連接到EJB:有區別。你真的在找什麼? – kolossus 2014-10-12 17:53:39
我在不同的服務器上部署了不同的EJB。我想同時從獨立的Java SE客戶端連接到兩個服務器/ EJB。通過連接Glassfish,我的意思是通過JNDI查找在該服務器上訪問EJB。 – salocinx 2014-10-13 06:39:00
EJB是安全的,所以我需要一個可以在服務器上進行身份驗證的地方(正在使用我的自定義JDBC領域)。但只要JVM正在運行,它就只能與一臺服務器一起工作,因爲屬性被設置爲JVM(System.setProperty(x,y))。 – salocinx 2014-10-13 06:41:56