How can I avoid the MarshalException for Java RMI? - java

I just finished a small program with java rmi and somehow it doesn't work. Everytime I want to start the server I'm getting the MarshalException. Are there any important points that I should be aware of them on how to implement the interface for the remote method invocation? I thought it would be possible to create an implementation but also include some additional methods like a constructor or private variables inside of the implementing class.
Shouldn't this just work?
Greetings

In order to be able to transfer objects you need to make them implement Serializable. And perhaps have a default (no-arg) constructor (this is not a requirement for serialization though)
As helios noted, not only the class, but all your field hierarchy (classes of fields, and the classes of their fields) must be Serializable)

Caused by:
java.lang.ClassNotFoundException:
vsys.ue04.server.RemoteChargeImplementation
There's your problem. That class is required at the client.

Related

Find all calls to interface implementers?

There are a large number of classes in this codebase which use a specific interface. However, picking a few at random, I've been unable to find one which is actually called anywhere; as such, I don't have a great idea of how to use it.
Is there a way in Eclipse to find every instance of any class which implements this interface?
In other words, suppose there exists an interface Interface, and classes ClassA, ClassB, ClassC, ..., ClassX, which all implement it. I want to see every point in the code where something like `ClassX obj = new ClassX(). Most of the classes I'm finding that implement this interface don't have any point where they're actually used; I assume they're for future use.
Open the interface class, hold Control and move your mouse to interface's name, select open implementation. That's the simplest and easiest way to do.
Yes, highlight the interface name and hit F4 or right click -> Open type hierarchy.
Update after OP's edit:
If you are using a framework that uses dependency injection like spring probably you don't find any reference because some of the implementations are defined in a xml file.
Also consider if some implementations are created and invoked via reflection.
Some classes might be loaded during runtime e.g. using reflection. To catch-them-all you can set a method entry breakpoint on the interface method. This is explained in this answer. That way all calls to implementation methods will suspend the JVM regardless of what is the object type.
Do note that unlike the line breakpoints the method breakpoints will really slow down the performance of the JVM.

How to prevent client from seeing internal private classes in Android library ?

I have a library with several packages-
lets say
package a;
package b;
inside package a I have public a_class
inside package b I have public b_class
a_class uses b_class.
I need to generate a library from this , but I do not want the Client to see b_class.
The only solution I know of is to flatten my beautifully understandable packages to single package and to use default package access for b_class.
Is there another way to do so ? maybe using interfaces or some form of design pattern ??
If you reject to move the code to an individual, controlled server, all you can do is to hinder the client programmer when trying to use your APIs. Let's begin applying good practices to your design:
Let your packages organized as they are now.
For every class you want to "hide":
Make it non-public.
Extract its public API to a new, public interface:
public interface MyInterface {...}
Create a public factory class to get an object of that interface type.
public class MyFactory
{
public MyInterface createObject();
}
So far, you have now your packages loosely coupled, and the implementation classes are now private (as good practices preach, and you already said). Still, they are yet available through the interfaces and factories.
So, how can you avoid that "stranger" clients execute your private APIs? What comes next is a creative, a little complicated, yet valid solution, based on hindering the client programmers:
Modify your factory classes: Add to every factory method a new parameter:
public class MyFactory
{
public MyInterface createObject(Macguffin parameter);
}
So, what is Macguffin? It is a new interface you must define in your application, with at least one method:
public interface Macguffin
{
public String dummyMethod();
}
But do not provide any usable implementation of this interface. In every place of your code you need to provide a Macguffin object, create it through an anonymous class:
MyFactory.getObject(new Macguffin(){
public String dummyMethod(){
return "x";
}
});
Or, even more advanced, through a dynamic proxy object, so no ".class" file of this implementation would be found even if the client programmer dares to decompile the code.
What do you get from this? Basically is to dissuade the programmer from using a factory which requires an unknown, undocumented, ununderstandable object. The factory classes should just care not to receive a null object, and to invoke the dummy method and check the return value it is not null either (or, if you want a higher security level, add an undocumented secret-key-rule).
So this solution relies upon a subtle obfuscation of your API, to discourage the client programmer to use it directly. The more obscure the names of the Macguffin interface and its methods, the better.
I need to generate a library from this , but I do not want the Client to see b_class. The only solution I know of is to flatten my beautifully understandable packages to single package and to use default package access for b_class. Is there another way to do so ?
Yes, make b_class package-private (default access) and instantiate it via reflection for use in a_class.
Since you know the full class name, reflectively load the class:
Class<?> clz = Class.forName("b.b_class")
Find the constructor you want to invoke:
Constructor<?> con = clz.getDeclaredConstructor();
Allow yourself to invoke the constructor by making it accessible:
con.setAccessible(true);
Invoke the constructor to obtain your b_class instance:
Object o = con.newInstance();
Hurrah, now you have an instance of b_class. However, you can't call b_class's methods on an instance of Object, so you have two options:
Use reflection to invoke b_class's methods (not much fun, but easy enough and may be ok if you only have a few methods with few parameters).
Have b_class implement an interface that you don't mind the client seeing and cast your instance of b_class to that interface (reading between the lines I suspect you may already have such an interface?).
You'll definitely want to go with option 2 to minimise your pain unless it gets you back to square one again (polluting the namespace with types you don't want to expose the client to).
For full disclosure, two notes:
1) There is a (small) overhead to using reflection vs direct instantiation and invocation. If you cast to an interface you'll only pay the cost of reflection on the instantiation. In any case it likely isn't a problem unless you make hundreds of thousands of invocations in a tight loop.
2) There is nothing to stop a determined client from finding out the class name and doing the same thing, but if I understand your motivation correctly you just want expose a clean API, so this isn't really a worry.
When using Kotlin, you can use the internal modifier for your library classes.
If I understand correctly you are asking about publishing your library for 3rd party usage without disclosing part of your source? If that's the case you can use proguard, which can obfuscate your library. By default everything will be excluded/obfuscated, unless you specify things you want to exclude from being obfuscated/excluded.
If you want to distribute [part of] your code without the client being able to access it at all, that means that the client won't be able to execute it either. :-O
Thus, you just have one option: Put the sensible part of your code into a public server and distribute a proxy to access it, so that your code would be kept and executed into your server and the client would still be able to execute it through the proxy but without accessing it directly.
You might use a servlet, a webservice, a RMI object, or a simple TCP server, depending on the complexity level of your code.
This is the safest approach I can think of, but it also deserves a price to pay: In addition to complexing your system, it would introduce a network delay for each remote operation, which might be big deal depending on the performance requirements. Also, you should securize the server itself, to avoid hacker intrussions. This could be a good solution if you already have a server that you could take advantage of.

GWT serialize a class extending a TreeSet

I have a GWT shared-package class as follows:
public class MyCustomClass extends TreeSet<MyCustomType> implements Serializable, IsSerializable {
// ... a whole bunch of methods
}
I am trying to send an instance of the class as an object encapsulated in another class, through RPC.
The problem is the TreeSet, as GWT refuses to serialize it, no matter what I do. I get an error during runtime:
SEVERE: my-service: An IncompatibleRemoteServiceException was thrown while processing this call.
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: java.lang.ClassNotFoundException: http:
at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:323)
So, I have all the serialization pre-requisites (default constructor, no final fields, getters and setters, all my instance variables are serializable, implement interfaces, etc.), but this continues to happen.
The thing is, when I switch from TreeSet to using an ArrayList instead, everything works fine. In my understanding, this is because I am already using ArrayLists in a number of services, so GWT knows to whitelist it in the serialization policies.
That understanding came because of this thread. And I've tried the proposed solution from the accepted answer (create a "dummy" service and put a TreeSet there, I even created a dummy class in my client package and put a TreeSet as a field), but no luck.
I checked my .gwt.xml just in case, the TreeSet is not added as a serialization exception.
So, I am pretty much stuck at this point, my workaround is to use the ArrayList and re-pack it into a transient set, but I do not really like that approach.
Any help would be highly appreciated.
(using GWT 2.6)
Update: MyCustomType implements the Comparable<MyCustomType> interface, and there is no custom comparator provided to the TreeSet.
May be MyCustomType doesn't implement java.lang.Comparable
It works fine for ArrayList<MyCustomType> but not for TreeSet<MyCustomType>
--EDIT--
HashSet<MyCustomType> or LinkedHashSet<MyCustomType> are working fine.
After getting data at client side just use
new TreeSet<MyCustomType>(<retured HashSet<MyCustomType>)
There is no need of iterating it because it is ordered by <Comparable<MyCustomType>.

Are there any other possible reasons for getting a GWT Serialization Policy exception?

I've been poking through this for about a week or so, now, and haven't found anything. I'm building an application with GWT, Hibernate, and Gilead, and I'm attempting to make an rpc call that loads a list of LightEntity objects from the database. This call worked perfectly, right up until I made a minimal change to my rpc interface - I added a deleteLightEntity method. Then I started receiving this error:
Type 'com.blah.shared.DomainObject' was not included in the set of types which can be
serialized by this SerializationPolicy or its Class object could not be loaded. For
security purposes, this type will not be serialized."
... which is normally characteristic of objects that don't have a no-args constructor, or perhaps don't implement Serializable or IsSerializable. Except my DomainObjects all do. And they all worked properly before I added this method to the rpc. I've even tried removing the method I added and recompiling, and it doesn't seem to work. I have also manually deleted the generated .gwt.rpc files, and cleared my browser cache. If anyone has any idea what could be causing these troubles, I would be very glad to hear it :)
If your class implements Serializable (and not IsSerializable), it will only be included in the serialization policy if it is referenced in the RPC interface, so check that.
If you have a reason not to reference that class you could use this workaround.
Also, since the error mentions the class DomainObject, which I assume is your global superclass, I would try to make it implement Serializable or IsSerializable too (in addition to its subclasses).
It would also help if you show us some source code.

How can I run my code upon class load?

Is there a feasible way to get my own code run whenever any class is loaded in Java, without forcing the user explicitly and manually loading all classes with a custom classloader?
Without going too much into the details, whenever a class implementing a certain interface read its annotation that links it with another class, and give the pair to a third class.
Edit: Heck, I'll go to details: I'm doing an event handling library. What I'm doing is having the client code do their own Listener / Event pairs, which need to be registered with my library as a pair. (hm, that wasn't that long after all).
Further Edit: Currently the client code needs to register the pair of classes/interfaces manually, which works pretty well. My intent is to automate this away, and I thought that linking the two classes with annotations would help. Next, I want to get rid of the client code needing to keeping the list of registrations up to date always.
PS: The static block won't do, since my interface is bundled into a library, and the client code will create further interfaces. Thus, abstract classes won't do either, since it must be an interface.
If you want to base the behavior on an interface, you could use a static initializer in that interface.
public interface Foo{
static{
// do initializing here
}
}
I'm not saying it's good practice, but it will definitely initialize the first time one of the implementing classes is loaded.
Update: static blocks in interfaces are illegal. Use abstract classes instead!
Reference:
Initializers (Sun Java Tutorial)
But if I understand you right, you want the initialization to happen once per implementing class. That will be tricky. You definitely can't do that with an interface based solution. You could do it with an abstract base class that has a dynamic initializer (or constructor), that checks whether the requested mapping already exists and adds it if it doesn't, but doing such things in constructors is quite a hack.
I'd say you cleanest options are either to generate Code at build time (through annotation processing with apt or through bytecode analysis with a tool like asm) or to use an agent at class load time to dynamically create the mapping.
Ah, more input. Very good. So clients use your library and provide mappings based on annotations. Then I'd say your library should provide an initializer method, where client code can register classes. Something like this:
YourLibrary.getInstance().registerMappedClasses(
CustomClass1.class,
CustomClass2.class,
CustomClass3.class,
CustomClass4.class
)
Or, even better, a package scanning mechanism (example code to implement this can be found at this question):
YourLibrary.getInstance().registerMappedClassesFromPackages(
"com.mycompany.myclientcode.abc",
"com.mycompany.myclientcode.def"
)
Anyway, there is basically no way to avoid having your clients do that kind of work, because you can't control their build process nor their classloader for them (but you could of course provide guides for classloader or build configuration).
If you want some piece of code to be run on any class loading, you should:
overwrite the ClassLoader, adding your own custom code at the loadClass methods (don't forget forwarding to the parent ClassLoader after or before your custom code).
Define this custom ClassLoader as the default for your system (here you got how to do it: How to set my custom class loader to be the default?).
Run and check it.
Depending on what kind of environment you are, there are chances that not all the classes be loaded trouugh your custom ClassLoader (some utility packages use their own CL, some Java EE containers handle some spacific areas with specific classLoaders, etc.), but it's a kind of aproximation to what you are asking.

Categories

Resources