What does Naming.lookup() do? - java

I have been going through a very simple example to set up a Remote Method Invocation application and while going through the client side code I am not able to understand one code as shown below. Definitely, gaps in my knowledge because I though an interface cannot have objects unless you use Anonymous Inner Class. So in the code below how did we creat an object of Remote Interface. It seems some sort of type-casting to me if I had to guess.
import java.rmi.*;
public class HelloClient {
public static void main(String args[]) {
try {
if (args.length < 0) {
System.err.println("usage: java HelloClient string …\n");
System.exit(1);
}
HelloInterface hello = (HelloInterface)Naming.lookup("//localhost/Hello");
This last line is what I am not able to understand what exactly is happening here with (HelloInterface) part?

HelloInterface hello = (HelloInterface)Naming.lookup("//localhost/Hello");
This Naming.lookup() call inspects the RMI Registry running in the localhost for a binding under the name "Hello".
It returns an Object that has to be cast to whatever remote interface you're expecting it to be.
You can then use that object to call the remote methods defined in the interface.
I thought an interface cannot have objects unless you use Anonymous Inner Class.
I have no idea what you're talking about here. Any class can implement an interface. This is rather basic.
So in the code below how did we create an object of Remote Interface
We didn't. We got it as a return value from the Registry, where it was put by the server.
It seems some sort of type-casting to me if I had to guess.
No need to guess. That's exactly what it is. There is only one 'sort' of typecasting, and this is how you write it. This is also rather basic.

HelloInterface hello = (HelloInterface)Naming.lookup("//localhost/Hello");
What is this mean ?
It is basically looking for an object in the server object pool registered with a name //localhost/Hello. this is called JNDI name
Depending on the type of server, this can be configured within the server configuration file.

Related

readObject throwing ClassNotFoundException when deserializing objects from independent class [duplicate]

I'm trying to pick up Java and wanted to test around with Java's client/server to make the client send a simple object of a self defined class(Message) over to the server. The problem was that I kept getting a ClassNotFoundException on the server side.
I think the rest of the codes seem to be alright because other objects such as String can go through without problems.
I had two different netbeans projects in different locations for client and server each.
Each of them have their own copy of Message class under their respective packages.
Message class implements Serializable.
On the client side, I attempt to send a Message object through.
On the server side, upon calling the readObject method, it seems to be finding Message class from the client's package instead of it's own. printStackTrace showed: "java.lang.ClassNotFoundException: client.Message" on the server side
I have not even tried to cast or store the object received yet. Is there something I left out?
The package name and classname must be exactly the same at the both sides. I.e. write once, compile once and then give the both sides the same copy. Don't have separate server.Message and client.Message classes, but a single shared.Message class or something like that.
If you can guarantee the same package/class name, but not always whenever it's exactly the same copy, then you need to add a serialVersionUID field with the same value to the class(es) in question.
package shared;
import java.io.Serializable;
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
// ...
}
The reason is, that the readObject() in ObjectInputStream is practically implemented as:
String s = readClassName();
Class c = Class.forName(s); // Here your code breaks
Object o = c.newInstance();
...populate o...

How is this interface being instantiated?

This is from the Minecraft server source code, also called the Minecraft Bukkit API, now you know as much as I do.
There is an interface called Server:
public interface Server extends PluginMessegeRecipient {
public String getVersion();
}
PluginMessageRecipient is an interface also.
There is a class called Bukkit that instantiates Server:
public final class Bukkit {
private static Server server;
}
Inside methods in the Bucket class they invoke methods from the server object. For example:
server.getVersion();
The thing is, there is no code for getVersion in the Server interface, just a method signature. There is also no code in the PluginMessageRecipient interface nor does it extend anything.
I have read all the questions and answers on SO that say I need an anonymous class or an inner class and this does not seem to fit those solutions.
There is a class called Bucket that instantiates Server:
Actually Bucket doesn't instantiate Server. The class Bucket contains a reference to a Server. You haven't shown how that got set so we don't know the actual class.
However, it is guaranteed that what is assigned to that reference (Bucket.server), assuming it's not null, is a an object of some concrete class that implements Server. That class will provide an implementation of getVersion() and that is what is being called.
Bukkit is just a Modding API. If you want to implement Bukkit, you need to create such an instance yourself and pass it there.
Take for example the unit tests that Bukkit includes:
https://github.com/Bukkit/Bukkit/blob/f210234e59275330f83b994e199c76f6abd41ee7/src/test/java/org/bukkit/TestServer.java#L77
A real implementation that allows you to run a Bukkit server is Spigot.
If I recall correctly, the particular concrete class that's being selected is determined at runtime via reflection. Because Minecraft is not open source, all the developers have are the obfuscated compiled class files to work with.
The code searches through each class file within the minecraft jar, searching for a class that matches certain conditions, and then, using a bytecode library, force that class to implement that interface.
For example, let's say that the following (obfuscated) class was the real Server class within the Minecraft code
class a {
String x_x317() {
return q_q98;
}
static a a_a1;
static String q_q98 = "1.9.4";
}
In this case, the method x_x317 returns the version string. The tool that allows them too hook into this class might do it based on the following conditions:
The class has default access
The class has only one default access static reference to itself
The class has only one default access static String field.
The class has a single method, that has default access, that returns String, and the returned value is the FieldRef found in 3.
This generally returns only one class. In the case that multiple are returned (usually in the dev phase of the new Bukkit version), they get more specific with their conditions to ensure that they only get the right class returned. They do this for every field, class, and method they need to identify.
Since they now know which exact class is the Server class, they can go ahead and make changes to it. First they would need to implement the interface
class a implements org.bukkit.Server
And then implement the method
class a implements org.bukkit.Server {
String x_x317() {
return q_q98;
}
public String getVersionNumber() {
return x_x317();
}
static a a_a1;
static String q_q98 = "1.9.4";
}
Now, we have a class that conforms to the Bukkit API.
When they need to instantiate that class, they just do something along the lines of
Server server = findAndTransformServerClassFromMinecraftJar();
// ...
Server findAndTransformServerClassFromMinecraftJar() {
// load classes from jar
// map them to the appropriate interfaces
// transform and hook the required classes and methods
Class<?> serverClass = doTheFirstThreeSteps();
return (Server) serverClass.newInstance();
}

How to "proxy" a method in Java

First off, I'm not sure how to best word my solution so if I seem to be babbling at times then please consider this.
There is an interface in a library I wish to modify without touching the physical code,
public interface ProxiedPlayer {
// .. other code
public void setPermission(String permission, boolean state);
}
I have written a third party library for handling permissions and having to hook into my API to edit permissions may be a step some developers do not want to take. So I ask that when setPermission is called is it possible to have it invoke my invoke the appropriate method in my library that will handle permission setting whilst ignoring the pre-programmed code or not?
Here is the full interface I am attempting to proxy.
I have looked into the Java Proxy class but it seems you need an instance of the object you're trying to proxy in the first place. Given that the method can be called any time I do not believe this to be my solution but will happily stand corrected.
I do not have control over instantiation of classes implementing the ProxiedPlayer interface.
EDIT: Ignorant me, there several events that I can subscribe to where it is possible to get an instance of the player, would this be the appropriate place to attempt to proxy the method? One of these events is fired when a player joins the server and getting the instance of the player is possible.
Would the Proxy code need to be called for every instance of the ProxiedPlayer interface or is it possible to simply proxy every invocation of the method in an easier way?
My library is a plugin loaded after everything else that is essential has finished loading.
Edit #2:
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class InvocationProxy implements InvocationHandler {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ProxiedPlayer player = (ProxiedPlayer) proxy;
if(method.getName().equals("setPermission")) {
// Call my code here?
}
return method.invoke(player, args);
}
}
Would something along the lines of what I have above work or am I barking up the wrong tree entirely?
If you do not want to touch the original source, then you only solve this problem by using a Java agent that redefines any class that implements the ProxiedPlayer interface to enforce your security check before calling the actual method. AspectJ together with a load-time-weaving agent was already mentioned as a possible solution for this but you can also implement a pure Java solution using my library Byte Buddy:
public class InterceptionAgent {
public static void premain(String arguments,
Instrumentation instrumentation) {
new AgentBuilder.Default()
.rebase(isSubtypeOf(ProxiedPlayer.class))
.transform(new AgentBuilder.Transformer() {
#Override
public DynamicType.Builder transform(DynamicType.Builder builder) {
return builder.method(named("setPermission"))
.intercept(MethodDelegation.to(MyInterceptor.class)
.andThen(SuperMethodInvocation.INSTANCE));
}
}).installOn(instrumentation);
}
}
With this agent, you more or less specify that you want to redefine any class that is a subtype of ProxiedPlayer to redefine (any) method named setPermisson in order to call a MyInterceptor (that would be your code) and to subsequently call the original implementation.
Note that the suggested implementation assumes that all classes implementing ProxiedPlayer implement the method of this interface and that there is only a single method of this signature. This might be too simple but it shows what direction to go.

How to invoke methods of a class (in java) when class name and method name are stored in two different strings

Well, not sure if the question sounds a little weird but let me try to put forth the clarification :
I have a JSP page. On this JSP page, I am calling a java class defined in one of my packages under my projects. This class connects to database and access a table which has got fields namely - functionname, function class. Now I am able to retrieve in my JSP the two strings, lets say -
String funName = "ComFunctions";
String className = "funLog");
Now, I want to invoke this function using this class name i.e. basically something like - className.funName
Is it possible in Java? Actually, these functions and class names will be retrieved in a for loop, so I can't directly call using real classname but have to use strings.
Kindly suggest if there is a way or worl around or if the question is still unclear.
I tried the following approach so far but no luck -
Class c = Class.forName(className);
Object o = c.newInstance();
Method m = c.getMethod(funName, String.class); // Not sure what is supposed to be second parameter here i.e. after funName
Error - the above code gives " No class found error". And i made sure that class is there under the package. Even adding package name i.e. packge.classname didnt help and it says "Symbol not found" for package name.
Any pointers please?
Example class that I am trying to invoke -
package mypackage;
public class ComFunctions extends WDriverInitialize{
public static void main(String[] args){
}
public static void funLog(String username){
System.out.println(userName);
}
}
You need to make sure the compiled class is in the webapp's classpath (ie, WEB-INF/classes) and use the FQN (ie, add the package name). You could also make a JAR file of your classes and add that to the WEB-INF/lib folder.
Also, the extra parameter in getMethod is to fetch a method with the matching parameters (ie, in your example, one that takes a String
You're missing one piece of the puzzle, and that's the method arguments. Without it, you can't really be sure what method funName is referring to, and what arguments to pass to it.
And of course, the class needs to be in the classpath.

Splitting remote EJB functionality between different remote objects

I am working on a legacy system, where there is a remote bean that has become too big and monolithic, and I would like to keep separate the new functionality I that need to add.
My initial idea was, instead of adding my new methods to the existing interface, create a new interface with all my stuff and add a single method that returns a remote object implementing my interface.
The problem I am facing now is that when I'm invoking the method that returns my object, the runtime tries to serialize it instead of sending the stub.
The code layout is more or less like this:
#Stateless
public class OldBean implements OldRemoteInterface {
//lots of the old unrelated methods here
public MyNewStuff getMyNewStuff() {
return new MyNewStuff();
}
}
#Remote
public interface OldRemoteInterface {
//lots of the old unrelated methods declared here
MyNewStuff getMyNewStuff();
}
public class MyNewStuff implements NewRemoteInterface {
//methods implemented here
}
#Remote
public interface NewRemoteInterface {
//new methods declared here
}
And the exception I am getting is:
"IOP00810267: (MARSHAL) An instance of class MyNewStuff could not be marshalled:
the class is not an instance of java.io.Serializable"
I have tried to do it "the old way", extending the java.rmi.Remote interface instead of using the ejb #Remote annotation, and the exception I get is:
"IOP00511403: (INV_OBJREF) Class MyNewStuff not exported, or else is actually
a JRMP stub"
I know I must be missing something that should be obvious... :-/
your approach here is a bit confusing. when you created the new interface, the next step should have been to have the old bean implement the new interface, like so:
public class OldBean implements OldRemoteInterface, NewRemoteInterface {
Your old bean would get larger, yes, but this is the only way you can expand the functionality of your old bean without creating a new bean or touching the old interface.
The object being returned by getNewStuff() is just a plain object -- it is not remote. That's why you're getting serialization errors, because RMI is trying to transfer your NewRemoteInterface instance across the network. Annotating it with #Remote doesn't do anything (until you actually use the interface on a bean, deploy that bean and then retrieve it using DI or Contexts)

Categories

Resources