no such object in table when calling registry.lookup - java

i am having a trouble when trying to run communication between server and client using RMI. My code is attached below. Server runs fine, i can see listening port in list of pc ports, client fails on registry.lookup. I didnt find any similar problem. Please help.
Server:
public class Main {
private static int port = Registry.REGISTRY_PORT;
private static Registry registry;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
if (args.length == 1) {
try {
port = Integer.parseInt(args[0]);
}
catch (NumberFormatException e) {
System.out.println("Port number is not valid!");
System.exit(0);
}
}
if (System.getSecurityManager() == null)
System.setSecurityManager(new RMISecurityManager());
String name = "DBInterface";
System.out.println("Starting server.");
try {
DBInterface DBInterface = new DBClass();
DBInterface stub = (DBInterface) UnicastRemoteObject.exportObject(DBInterface, 5000);
registry = LocateRegistry.createRegistry(port);
registry.rebind(name, stub);
}
catch (RemoteException e)
{
System.out.println(e.getMessage());
}
System.out.println("Server succesfully started.");
}
}
Client:
public class Client {
private static String ipAddress = "localhost";
private static int port = Registry.REGISTRY_PORT;
private static String confFile = "";
public static DBInterface dbServer = null;
public static String name = "DBInterface";
public static void main(String[] args) {
System.out.println("Starting client.");
if (System.getSecurityManager() == null)
System.setSecurityManager(new RMISecurityManager());
if (args.length == 3) {
try {
ipAddress = args[0];
port = Integer.parseInt(args[1]);
confFile = args[2];
}
catch (NumberFormatException e) {
System.out.println("Port number is not valid!");
System.exit(0);
}
}
else
{
System.out.println("Some parameter is missing!");
System.out.println("Valid parameters are: IP(0) Port(1) Config_file_name(2).");
}
ArrayList<ArrayList<String>> commands = Tools.loadConfigFile(confFile);
Iterator<ArrayList<String>> commandsIterator = commands.iterator();
Registry registry;
try {
registry = LocateRegistry.getRegistry(ipAddress, port);
dbServer = (DBInterface) registry.lookup(name); //code fails here
} catch (RemoteException e) {
System.out.println(e.getMessage()); //"no such object in table" is printed on the screen
} catch (NotBoundException e) {
System.out.println(e.getMessage());
}
Tools tools = new Tools(dbServer);
...

What you describe is basically impossible. That exception means that the stub you are using, in this case a Registry, no longer refers to a live exported object in the target JVM. However as Registry stubs are created locally there is no opportunity for them to expire at all. The only mechanism would be the Registry you created exiting, but the static Registry reference should prevent that.
I would change a few things though:
DBInterface stub = (DBInterface) UnicastRemoteObject.exportObject(DBInterface, 5000);
registry = LocateRegistry.createRegistry(port);
Reverse these two lines, and use port for both the Registry and the export. You don't need two ports. Also, in all your catch blocks, never just suppress the exception message in favour of your own. You should always at least log the actual exception message.

Related

Change JVM Properties Using WebSphere MBeans

I'm trying to create a java program that will edit the class path properties of the JVM on WebSphere. I am now able to connect the program to the server and also find the node, but I don't know what to do next. Which MBean should I use to be able to find the JVM Classpath and configure it? I know I can edit it on the AdminConsole itself, but for this task, I would really have to do it using a Java Program.
I am also not allowed to use wsadmin and jacl/jython scripts.
Here is my code so far:
public class Expi
{
private AdminClient adminClient;
private ObjectName nodeAgent;
private AdminService adminSF;
String hostName = "localhost";
String hostPort = "8880";
String nodeName = "node1";
String servName = "server1";
public static void main(String [] args) throws NamingException, AdminException
{
Expi xp = new Expi();
xp.createAdminClient();
xp.getNodeAgentMBean(nodeName);
xp.testMB();
}
private void createAdminClient()
{
// Set properties for the connection
Properties connectProps = new Properties();
connectProps.setProperty(
AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
connectProps.setProperty(AdminClient.CONNECTOR_HOST, hostName);
connectProps.setProperty(AdminClient.CONNECTOR_PORT, hostPort);
connectProps.setProperty(AdminClient.USERNAME, hostName);
connectProps.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "false");
// Connection Status Update
try
{
adminClient = AdminClientFactory.createAdminClient(connectProps);
System.out.println("Connected to SOAP Connection!");
}
catch (java.lang.Exception e)
{
System.out.println("Exception creating admin client: " + e);
System.exit(-1);
}
}
private void getNodeAgentMBean(String nodeName) throws NamingException
{
// Finding the specified node
try
{
String query = "WebSphere:type=Server,node="+ nodeName + ",*";
ObjectName queryName = new ObjectName(query);
Set s = adminClient.queryNames(queryName, null);
if (!s.isEmpty())
{
nodeAgent = (ObjectName)s.iterator().next();
System.out.println("Specified Node Found:" + nodeName);
}
else
{
System.out.println("Node agent MBean was not found");
System.exit(-1);
}
}
catch (MalformedObjectNameException e)
{
System.out.println(e);
System.exit(-1);
}
catch (java.lang.Exception e)
{
System.out.println(e);
System.exit(-1);
}
}
private void testMB() //find the correct MBean and use it to edit the values
{
AdminServiceFactory.getAdminService();
AdminServiceFactory.getMBeanFactory();
}
}
Any help would really be appreciated. Thank you!
You can execute the admin command using the AdminClient API. It is very difficult for to find out specific action since it is not well documented like JACL or JYTHON.
Sample available below for simple "listNodes" command. You can use the same approach to "listServers" and get the specific server object you want to modify. Once the server object is obtained, you can look at the same documentation below for executing command on specific target object.
AdminCommand cmd = cmdMgr.createCommand("listNodes");
cmd.setConfigSession(session);
AsyncCommandClient asyncCmdClientHelper =
new AsyncCommandClient(session, null);
asyncCmdClientHelper.execute(cmd);
CommandResult result = cmd.getCommandResult();
if (result.isSuccessful()) {
System.out.println("Successfully executed the command");
System.out.println("Result: ");
Object resultData = result.getResult();
if (resultData instanceof Object[]) {
Object[] resDataArr = (Object[])resultData;
for (Object resData : resDataArr) {
System.out.println(resData);
}
} else {
System.out.println(resultData);
}
} else {
System.out.println("Failed to execute the command");
result.getException().printStackTrace();
}
Documentation Link : https://www.ibm.com/developerworks/websphere/techjournal/1303_samantary/1303_samantary.html

How to do naming system with RMI in different hosts?

I have two java classes one is the client and the other is the server, in the client I have to give the server ip address, but I want to make it dynamique so the client knows the ip of a third machine(naming system) which search for the method (like DNS) and returns the ip address of the specific server who provides this method.
Edited:
classe client :
public class Client {
private Client() {}
public static void main(String[] args) {
String host = (args.length < 1) ? null : args[0];
try {
//Registry registry = LocateRegistry.getRegistry(host);
Registry registry = LocateRegistry.getRegistry("192.168.1.9",1091);
Calculator stub = (Calculator) registry.lookup("Hello");
String response = stub.add(4,2);
System.out.println("response: " + response);
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
server :
public class Server implements Calculator{
public Server() {}
public String add(int a,int b) {
return "Hello, a+b= "+(a+b);
}
public String sub(int a,int b) {
return "Hello, a-b= "+(a-b);
}
public static void main(String args[]) {
try {
Server obj = new Server();
Calculator stub = (Calculator) UnicastRemoteObject.exportObject(obj, 0);
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.createRegistry(1091);
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
You can't do this with the RMI Registry. Only a process running in the same host as the Registry can bind to it. You would have to use a different naming service such as LDAP.
However the rest of your description is what RMI already does. You look up a name in the Registry and it returns you a stub that knows how to communicate with the corresponding remote object.

How to solve java.security.AccessControlException

I need suggestions concerning the java.security.AccessControlException, I get when executing the following code. (I have consulted similar questions here but didn't success to make it work)
Here is my server code:
public class GetPageInfos extends UnicastRemoteObject implements RemoteGetInfo{
private static final String url="http://www.lemonde.fr/";
public class GetPageInfos extends UnicastRemoteObject implements RemoteGetInfo{
private static final String url="http://www.lemonde.fr/";
public GetPageInfos() throws RemoteException{
}
public String getSiteInfos() throws RemoteException {
Document doc;
try {
doc = Jsoup.connect(url).get();
String title = doc.title();
return "title is "+title;
} catch (IOException e) {
System.out.println("Faild! "+e.getMessage());
return "not found";
}
}
public static void main(String[] args){
try {
GetPageInfos infos= new GetPageInfos();
//System.setProperty("java.rmi.server.hostname","5lq04x1.gemalto.com");
Naming.rebind("RemoteGetInfo", infos);
/*GetPageInfos obj=new GetPageInfos();
RemoteGetInfo stub = (RemoteGetInfo) UnicastRemoteObject.exportObject(obj, 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("RemoteGetInfo", stub);
*/
System.out.println("server ready");
} catch (RemoteException e) {
System.out.println("GetPageInfos "+e.getMessage());
}
catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And here is my client code:
//RMI Client
public class PrintSiteInfos {
public static void main(String arg[])
{
System.setSecurityManager(new RMISecurityManager());
try
{
/*String host=null;
Registry registry = LocateRegistry.getRegistry(host);
RemoteGetInfo stub = (RemoteGetInfo) registry.lookup("RemoteGetInfo");
String response = stub.getSiteInfos();
System.out.println(response); */
RemoteGetInfo obj = (RemoteGetInfo) Naming.lookup( "RemoteGetInfo");
System.out.println(obj.getSiteInfos());
}
catch (Exception e)
{
System.out.println("PrintSiteInfos exception: " + e.getMessage());
e.printStackTrace();
}
}
}
So I got
exception: access denied ("java.net.SocketPermission" "127.0.0.1:1099" "connect,resolve")
I found that I have to pass a policy file which I have like:
grant {
permission java.security.AllPermission;};
But how? Anyother suggestions?
You may grant only the socket permission not all permissions (which might be a security risk). Thus something like:
grant {
permission java.net.SocketPermission "127.0.0.1:1099", "connect, resolve";
};
Two ways to do it:
1) As an argument at the command line
java -Djava.security.policy=mypolicyfile PrintSiteInfo
2) within the JRE environment:
Add the permission in the JRE_HOME/lib/security/java.policy file
Get rid of the security manager. You don't need it unless you're using the RMI codebase feature.

TcpSockets do not connect

I am trying to establish a TCP connection between a laptop as a client and a pc as a server.
My goal is to use the server to send messages between two android devices. The server has a public IP address. To test the connection, I have written two simple Java classes:
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public ServerSocket welcome;
public Socket soc;
public int listeningPort = /* default port */;
public TcpServer() {
}
public static void main(String[] args) {
TcpServer ms = new TcpServer();
if(args.length > 0) {
ms.listeningPort = Integer.parseInt(args[0]);
}
ms.listen();
}
public void listen() {
try {
welcome = new ServerSocket(listeningPort);
System.out.println(">>> listening on port " + listeningPort + " <<<");
soc = welcome.accept();
System.out.println(">>> got a new connection from "
+ soc.getInetAddress().toString() + " <<<");
while (true) {
try {
byte b[] = new byte[1024];
soc.getInputStream().read(b, 0, 1);
System.out.print((char) (b[0]));
} catch (Exception e) {
System.err.println(e);
}
}
} catch (Exception e) {
System.err.println(e);
}
}
}
import java.net.Socket;
public class TcpSendClient {
private String serverIp = /* some ip */;
public int port = /* default port */;
private SendThread st;
public TcpSendClient() {
}
public static void main(String[] args) {
TcpSendClient client = new TcpSendClient();
if(args.length > 0) {
client.port = Integer.parseInt(args[0]);
}
client.send();
}
public void send() {
System.out.println("Try to connet to " + serverIp + " via Port" + port);
st = new SendThread(serverIp, port);
st.start();
}
class SendThread extends Thread {
private Socket soc;
public SendThread(String theIp, int thePort) {
try {
soc = new Socket(theIp, thePort);
} catch (Exception e) {
System.err.println(e);
}
}
public void run() {
try {
while (true) {
String toSend = "Hello ";
soc.getOutputStream().write(toSend.getBytes());
Thread.sleep(800);
System.out.println("sent");
}
} catch (Exception e) {
System.err.println(e);
}
}
}
}
When I run both Java files on the server pc, the connection works fine. It also worked if I set up a local Wi-Fi with one laptop and connect to it using another laptop.
But, when I run the client file from a laptop connected to the internet, I am not able to get a connection.
In the firewall on the Server, I opened a number of ports for the connection and the laptop I use as a client has the firewall disabled.
Apart from the firewall, I do not really know what to look into in order to get the connection running. Any ideas as to the cause of my problem and a solution?
I found the solution: The windows firewall was still blocking the ports for Java. It took me a little longer to figure this out, because I was not registered as admin on that pc and could not see the rules.

How to set focus the already running application?

I am using a ServerSocket port to run one instance only of my Java Swing application, so if a user tries to open another instance of the program, i show him a warning that "Another instance is already open". This works fine, but instead of showing this message i want to set focus on the running application itself, like some programs does (MSN Messenger), even if it was minimized.
Is there a solution for this for various operating systems ?
Since you use a server socket I assume that you use the java.net.BindException to detect that you application is already running. If you start a second instance you could send a control message which instructs you first app to normalize (if minimized) before exiting.
if (msg == BRING_TO_FRONT ) {
frame.setState(Frame.NORMAL);
frame.toFront();
}
I don't know if this is absolutely right, but here's the final code i've used and it works fine for me :
public class Loader {
private static final int PORT = 9999;
private static ServerSocket serverSocket = null; // Server
private static Socket socket = null; // CLient
private static final String focusProgram = "FOCUS";
public static void main(String[] args) {
if( !isProgramRunning() ) {
Main main = new Main();
main.setVisible( true );
}
else {
System.exit( 2 );
}
}
private static boolean isProgramRunning() {
try {
serverSocket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1})); // Bind to localhost adapter with a zero connection queue.
SwingWorker<String, Void> anotherThread = new SwingWorker<String, Void>() { // Do some code in another normal thread.
#Override
public String doInBackground() { // This method is to execute a long code in the other thread in background.
serverSocketListener();
return "";
}
};
anotherThread.execute(); // Execute the other tread.
}
catch (BindException e) {
System.err.println("Already running.");
clientSocketListener();
return true;
}
catch (IOException e) {
System.err.println("Unexpected error.");
e.printStackTrace();
return true;
}
return false;
}
public static void serverSocketListener() { // Server socket
try {
System.out.println( "Listener socket opened to prevent any other program instance." );
socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
if( in.readLine().equals( focusProgram ) ) { // Restore the opened instance however you want.
Global.getCurrentFrame().setState(Frame.NORMAL);
Global.getCurrentFrame().toFront();
}
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
public static void clientSocketListener() { // Client socket
try{
socket = new Socket(InetAddress.getByAddress( new byte[] {127,0,0,1}), PORT );
PrintWriter out = new PrintWriter( socket.getOutputStream(), true );
out.println( focusProgram );
} catch (IOException e) {
System.out.println("No I/O");
System.exit(1);
}
}
}

Categories

Resources