Java BrowserLauncher throwing InvocationTargetException - java

I'm using the BrowserLauncher2 library for opening the user's default web browser from my Swing app, but it's throwing a very confusing exception:
public static void openURL(String url) {
try{
BrowserLauncher launcher = new BrowserLauncher();
launcher.openURLinBrowser(url);
}catch(Exception e){
e.printStackTrace();
}
}
Exception:
edu.stanford.ejalbert.exception.BrowserLaunchingExecutionException: java.lang.reflect.InvocationTargetException
at edu.stanford.ejalbert.launching.macos.MacOs3_1BrowserLaunching.openUrl(MacOs3_1BrowserLaunching.java:61)
at edu.stanford.ejalbert.BrowserLauncherRunner.run(BrowserLauncherRunner.java:136)
at java.lang.Thread.run(Thread.java:613)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at edu.stanford.ejalbert.launching.macos.MacOs3_1BrowserLaunching.openUrl(MacOs3_1BrowserLaunching.java:58)
... 2 more
Caused by: java.security.AccessControlException: access denied (java.lang.RuntimePermission canOpenURLs)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264)
at java.security.AccessController.checkPermission(AccessController.java:427)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at com.apple.eio.FileManager.openURL(FileManager.java:229)
at com.apple.mrj.MRJPriv.openURL(MRJPriv.java:255)
at com.apple.mrj.MRJFileUtils.openURL(MRJFileUtils.java:206)
... 7 more

You are running your application with a SecurityManager set. Some code in the AccessControlContext (a.k.a. acc) does not have the required permission. Probably that code is your application code.

An InvocationTargetException always wraps another exception which was caused while invoking a method or constructor via reflection. To solve your problem, you need to look at the exception under it, the IllegalAccessException which as Tom Hawtin points out, is being thrown because of the SecurityManager.

First of all, BrowserLauncher does not support Mac OS < 10.2.
Also, on MacOS, BrowserLauncher launches the default browser, targeting a specific browser is not possible. You could try changing the default browser on your computer to see if that helps. Apparently this can be done by the following:
Start Safari -> Select Preferences -> in the General tab, find the Default web browser.

I was getting AccessControlExceptions with BrowserLauncher2 via an applet of mine. Your situation may be similar, because you are running your app with a SecurityManager.
I solved my problem by signing the BrowserLauncher2 jar with my certificate. If your user accepts your certificate, BrowserLauncher should have the permissions it needs to do its job.

Related

Java RMI NoClassDefFoundError for javax.json.JsonValue in Remote object

Running into Exception caused during call to UnicastRemoteObject.exportObject().
javax.json.jar is on the classpath and is used in many other places in the application without any problems.
This part of the application worked fine until I added a method that returned a JsonValue to the remote object.
Any ideas?
java.rmi.ServerError: Error occurred in server thread; nested exception is:
java.lang.NoClassDefFoundError: javax/json/JsonValue
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:416)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:275)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:252)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:378)
at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)
NOTE:
I also tried running the rmiregistry with codebase pointed directly at the javax.json.jar but the exception remains
rmiregistry -J-Djava.rmi.server.codebase=file:///JarLibrary/javax.json.jar &
Running into Exception caused during call to UnicastRemoteObject.exportObject().
No you aren't. See the stack trace. It's happening in Registry.bind().
You need to run the server with the java.rmi.server.codebase property set, but a file:// codebase URL isn't going to work unless either all the clients are running in the server host, in which case you don't really need the codebase feature at all, or it points to a shared folder in a form that both the Registry and the clients can use. It's usually HTTP.
But I question whether you need the codebase feature at all. You just have to ensure that the relevant jar file is on the CLASSPATH of both the Registry and the clients. The simplest way to ensure that for the Registry is to use LocateRegistry.createRegistry() in the server JVM instead of the external rmiregistry program.
I'm also wondering why you're using JSON at all. RMI is built over Object Serialization. You don't need to add another serializer.

EJB Compiling issues [duplicate]

Hi I have RMI application and now I try to invoke some methods at server from my client. I have following code:
public static void main(final String[] args) {
try {
//Setting the security manager
System.setSecurityManager(new RMISecurityManager());
IndicatorsService server = (IndicatorsService) Naming
.lookup("rmi://localhost/" + IndicatorsService.SERVICE_NAME);
DataProvider provider = new OHLCProvider(server);
server.registerOHLCProvider(provider);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
server Is correctly loaded, but when I am trying to call server.registerOHLCProvider(provider); I get these errors:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:336)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
at sk.fri.statistics.service.impl.IndicatorsServiceImpl_Stub.registerOHLCProvider(Unknown Source)
at sk.fri.statistics.service.Client.main(Client.java:61)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:296)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:375)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1574)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:290)
... 9 more
I have added my policy file as VM argument, here is how it looks like:
grant {
permission java.security.AllPermission;
}
It keeps saying something about disabled classloading, so I guess problem is somewhere there ...
Thanks!
Remote class loading can be tricky.
The original post doesn't include any information about the code base. It may be that the client's security configuration is correct, but it has no access to the remote code. The classes are loaded directly from the "code base" by the client. They are not presented to the client by the service over the RMI connection. The service merely references an external source for the classes.
The server should specify the system property java.rmi.server.codebase. The value must be a URL that is accessible to the client, from which the necessary classes can be loaded. If this is a file: URL, the file system must be accessible to the client.
And the other way around: If the server should be able to load classes from the client (like here), the client must set the code base property to a URL that is accessible to the server.
Every time you invoke a method on an RMI dynamic proxy, the MarshalInputStream (which extends ObjectInputStream to override resolveClass and resolveProxyClass) delegates to LoaderHandler to look in 3 places for the ClassLoader to use:
The ClassLoader of the proxy that is being invoked (technically, it uses a hack called latestUserDefinedLoader(): it walks up the stack, looking for the first method on the stack that is not part of JRE).
Thread-local contextClassLoader of the caller
Codebase ClassLoader if SecurityManager is enabled
If System property java.rmi.server.useCodebaseOnly=false, then the codebase ClassLoader uses URLs in the remote java.rmi.server.codebase. Note that the default value of useCodebaseOnly changed in JDK 7u21 so that remote codebase is not used anymore unless you change it!
Otherwise, the codebase ClassLoader uses URLs in the local java.rmi.server.codebase.
So there are a few possible reasons that you would get a ClassNotFoundException when invoking a Remote method:
If stack contains “no security manager: RMI class loader disabled”, then make sure to set a SecurityManager as described by others if you need remote class loading for both sides to get all the Remote interfaces and serializable classes.
If you are using remote class loading and it stopped working when you upgraded to JRE 7u21, then either set -Djava.rmi.server.useCodebaseOnly=true to match previous behavior, or set -Djava.rmi.server.codebase to a space-separated list of URLs on both the local and the remote sides. And make sure that computer can access those URLs.
If you are using a custom ClassLoader locally whose parent classloader defines some Remote interfaces, then make sure to call Thread.setContextClassLoader(ClassLoader) so that RMI will use that ClassLoader. (This was my problem: I had a SwingWorker that happened to be scheduled onto a worker thread that was created before the contextClassLoader was set on the EventDispatchThread). For example, A and C belong to your custom ClassLoader but B belongs to the parent ClassLoader, then when you call a.getB().getC(), the getB() call will use the custom classloader, but the getC() call will fail to find C in the latestUserDefinedClassLoader and will have to fall back to the contextClassLoader.
All of this is a cautionary tale on poor API design of ObjectInputStream. ObjectInputStream should have required you to pass a ClassLoader parameter, not try to find one haphazardly using latestUserDefinedLoader, contextClassLoader, and codebase.
I want to add something which may be helpful for some people, especially begginers.
I came here and searched for a solution for the above error, but being a beginner, I didn't know how to use security policies and specify the "java.rmi.server.codebase" attribute.
The simplest way to fix that error is to make sure that the classes of the objects to be sent over RMI are in the same path of packages.. In this way, both applications have the class in the same location relative to their main folder and the error will solve.
Example:
If you want to send an object of type MedicationDTO (which is serializable) from server to client, make sure that it is in the same package path.
In my case, in the server app, the object was in com.example.springdemo.dto and in the client app, it was in com.example.springdemo.service.dto.. The problem was that, using IntelliJ, because the service package had nothing in it, but an other package, their name was concatenated (service.dto) and I could not see that the path was not the same.
So, make sure that your classes have the same package path. (Solution for my case: MedicationDTO class has to be in both application in package: com.example.springdemo.dto.
I know this is not the best solution, it's just a 'little trick', but I would have been extremely happy to find this solution then, because it had saved me from a lot of wasted time to solve the problem.
I hope this will be helpful for those who want a quick fix to that error, because I think learning to use security managers and including codebase could be a little tricky and will take time.
You need the security manager at the server side, not only at the client side.
Without this, the server's RMI engine refuses to load classes from the client, as it can't guarantee that these won't do evil things on the server.
Do you need the RMI class loading at all? Couldn't the server already have the classes which the client tries to send?
I know my case is extremely special but maybe it helps others. I had the case that there were multiple applications on one server sharing the same registry with different paths of course. Wherever this registry is created (usually from the first application) the full classpath of all later applications must be specified in this first application. To sum it up:
Make sure policy is provided
Make sure classpath is full specified for all applications, clients and server
I know why it happens.
for example you start server in the project A,
but you use the Client in the project B to request this server,this is wrong.
So you should put the server and client in the same project.

Executing JNLP file throws a AccessControlException

I am trying to execute this jnlp application.
However, I keep receiving this security exception:
java.lang.ExceptionInInitializerError
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:399)
at java.lang.Class.newInstance0(Class.java:370)
at java.lang.Class.newInstance(Class.java:322)
at com.sun.javafx.applet.FXApplet2.init(FXApplet2.java:63)
at com.sun.deploy.uitoolkit.impl.fx.FXApplet2Adapter.init(FXApplet2Adapter.java:207)
at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.security.AccessControlException: access denied ("java.util.PropertyPermission" "java.net.useSystemProxies" "write")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:364)
at java.security.AccessController.checkPermission(AccessController.java:560)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.System.setProperty(System.java:783)
at ensemble.Ensemble2.<clinit>(Ensemble2.java:77)
... 10 more
I tried changing the security settings in the Java control panel (OSX 10.8.3), but they seem to be disabled and I cannot modify them (I do can check the "Enable Java content in the browser" option, but it is resetted when I click apply). This is shown in the following figure:
Is there another mechanism for bypassing the Java security manager and being able to execute a jnlp application ?
UPDATE:
After reinstalling Java I was finally able to change the security options in the Java Control panel (I did not do anything special, just reinstall it from scratch). Unfortunately, when I execute the jnlp application it dies silently without showing any errors. This problem could be related to the fact that I am using the jdk 1.8 (since the jnlp application requires javafx) and it is just a preview version (and OSX does not seem to like a lot Java these days...), it is my best guess but I cannot be completely sure.
Possible reasons for this:
I have heard that Java 7 on Mac is still not stable.
By default JNLP files run in a "sandbox" to prevent malicious code from wreaking havoc on your system. This sandbox restricts access to the local filesystem and local network. I imagine that system properties are restricted too, and it looks like the app is trying to write to them. To allow unrestricted access, you need to sign the JAR file and configure the JNLP file with <security><all-permissions/></security>

Java: no security manager: RMI class loader disabled

Hi I have RMI application and now I try to invoke some methods at server from my client. I have following code:
public static void main(final String[] args) {
try {
//Setting the security manager
System.setSecurityManager(new RMISecurityManager());
IndicatorsService server = (IndicatorsService) Naming
.lookup("rmi://localhost/" + IndicatorsService.SERVICE_NAME);
DataProvider provider = new OHLCProvider(server);
server.registerOHLCProvider(provider);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
server Is correctly loaded, but when I am trying to call server.registerOHLCProvider(provider); I get these errors:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:336)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
at sk.fri.statistics.service.impl.IndicatorsServiceImpl_Stub.registerOHLCProvider(Unknown Source)
at sk.fri.statistics.service.Client.main(Client.java:61)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:296)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:375)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1574)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:290)
... 9 more
I have added my policy file as VM argument, here is how it looks like:
grant {
permission java.security.AllPermission;
}
It keeps saying something about disabled classloading, so I guess problem is somewhere there ...
Thanks!
Remote class loading can be tricky.
The original post doesn't include any information about the code base. It may be that the client's security configuration is correct, but it has no access to the remote code. The classes are loaded directly from the "code base" by the client. They are not presented to the client by the service over the RMI connection. The service merely references an external source for the classes.
The server should specify the system property java.rmi.server.codebase. The value must be a URL that is accessible to the client, from which the necessary classes can be loaded. If this is a file: URL, the file system must be accessible to the client.
And the other way around: If the server should be able to load classes from the client (like here), the client must set the code base property to a URL that is accessible to the server.
Every time you invoke a method on an RMI dynamic proxy, the MarshalInputStream (which extends ObjectInputStream to override resolveClass and resolveProxyClass) delegates to LoaderHandler to look in 3 places for the ClassLoader to use:
The ClassLoader of the proxy that is being invoked (technically, it uses a hack called latestUserDefinedLoader(): it walks up the stack, looking for the first method on the stack that is not part of JRE).
Thread-local contextClassLoader of the caller
Codebase ClassLoader if SecurityManager is enabled
If System property java.rmi.server.useCodebaseOnly=false, then the codebase ClassLoader uses URLs in the remote java.rmi.server.codebase. Note that the default value of useCodebaseOnly changed in JDK 7u21 so that remote codebase is not used anymore unless you change it!
Otherwise, the codebase ClassLoader uses URLs in the local java.rmi.server.codebase.
So there are a few possible reasons that you would get a ClassNotFoundException when invoking a Remote method:
If stack contains “no security manager: RMI class loader disabled”, then make sure to set a SecurityManager as described by others if you need remote class loading for both sides to get all the Remote interfaces and serializable classes.
If you are using remote class loading and it stopped working when you upgraded to JRE 7u21, then either set -Djava.rmi.server.useCodebaseOnly=true to match previous behavior, or set -Djava.rmi.server.codebase to a space-separated list of URLs on both the local and the remote sides. And make sure that computer can access those URLs.
If you are using a custom ClassLoader locally whose parent classloader defines some Remote interfaces, then make sure to call Thread.setContextClassLoader(ClassLoader) so that RMI will use that ClassLoader. (This was my problem: I had a SwingWorker that happened to be scheduled onto a worker thread that was created before the contextClassLoader was set on the EventDispatchThread). For example, A and C belong to your custom ClassLoader but B belongs to the parent ClassLoader, then when you call a.getB().getC(), the getB() call will use the custom classloader, but the getC() call will fail to find C in the latestUserDefinedClassLoader and will have to fall back to the contextClassLoader.
All of this is a cautionary tale on poor API design of ObjectInputStream. ObjectInputStream should have required you to pass a ClassLoader parameter, not try to find one haphazardly using latestUserDefinedLoader, contextClassLoader, and codebase.
I want to add something which may be helpful for some people, especially begginers.
I came here and searched for a solution for the above error, but being a beginner, I didn't know how to use security policies and specify the "java.rmi.server.codebase" attribute.
The simplest way to fix that error is to make sure that the classes of the objects to be sent over RMI are in the same path of packages.. In this way, both applications have the class in the same location relative to their main folder and the error will solve.
Example:
If you want to send an object of type MedicationDTO (which is serializable) from server to client, make sure that it is in the same package path.
In my case, in the server app, the object was in com.example.springdemo.dto and in the client app, it was in com.example.springdemo.service.dto.. The problem was that, using IntelliJ, because the service package had nothing in it, but an other package, their name was concatenated (service.dto) and I could not see that the path was not the same.
So, make sure that your classes have the same package path. (Solution for my case: MedicationDTO class has to be in both application in package: com.example.springdemo.dto.
I know this is not the best solution, it's just a 'little trick', but I would have been extremely happy to find this solution then, because it had saved me from a lot of wasted time to solve the problem.
I hope this will be helpful for those who want a quick fix to that error, because I think learning to use security managers and including codebase could be a little tricky and will take time.
You need the security manager at the server side, not only at the client side.
Without this, the server's RMI engine refuses to load classes from the client, as it can't guarantee that these won't do evil things on the server.
Do you need the RMI class loading at all? Couldn't the server already have the classes which the client tries to send?
I know my case is extremely special but maybe it helps others. I had the case that there were multiple applications on one server sharing the same registry with different paths of course. Wherever this registry is created (usually from the first application) the full classpath of all later applications must be specified in this first application. To sum it up:
Make sure policy is provided
Make sure classpath is full specified for all applications, clients and server
I know why it happens.
for example you start server in the project A,
but you use the Client in the project B to request this server,this is wrong.
So you should put the server and client in the same project.

Signed Java applet doesnt get permissions in Safari

I've got a signed java applet (using a self-signed-certificate) which has to access the user's file system. I have to do it, so please no replies ala "you shouldn't do it" :)
The thing is, when I execute the Applet from Firefox 3.0 / Mac, everything works as desired, I get all access just as it should.
When I use Safar 4 / Mac, I don't get access. The line I especially have problems with is System.getProperty() (although when I stub that out, the FS access doesn't work either)
String home = System.getProperty("user.home");
The Exception I get is the following:
java.security.AccessControlException: access denied (java.util.PropertyPermission user.home read)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264)
at java.security.AccessController.checkPermission(AccessController.java:427)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1285)
at java.lang.System.getProperty(System.java:628)
at de.samedi.searcher.Searcher.<init>(Searcher.java:49)
at de.samedi.searcher.Applet.getSearcher(Applet.java:193)
at de.samedi.searcher.Applet.getSearcher(Applet.java:187)
at de.samedi.searcher.Applet.addPatient(Applet.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at sun.plugin.javascript.invoke.JSInvoke.invoke(JSInvoke.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at sun.plugin.javascript.JSClassLoader.invoke(JSClassLoader.java:44)
at sun.plugin.liveconnect.PrivilegedCallMethodAction.run(SecureInvocation.java:658)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin.liveconnect.SecureInvocation$2.run(SecureInvocation.java:214)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin.liveconnect.SecureInvocation.CallMethod(SecureInvocation.java:192)
at sun.plugin.liveconnect.SecureInvocation.access$300(SecureInvocation.java:52)
at sun.plugin.liveconnect.SecureInvocation$CallMethodThread.run(SecureInvocation.java:123)
As I said, this works perfectly on Firefox. Gotta check Windows Browser today...
Any Ideas?
Once you have your jar compiled and signed you should run the -verify option to ensure its signed properly.
If the verification is ok look at the installed certificates on your browsers.
I haven't done anything in Safari only IE, but I imagine there is a place similar to I.E. where you can at least view the installed certificates. I would verify the certificate is installed.
Also make sure your code is running in a privileged block.
String home = System.getProperty("user.home");
will always throw an error in 1.4 or higher. Unless you have edited the java.policy file for All Permissions
Try using this in combination with your signed jar.
String home = (String) AccessController.doPrivileged(new PrivilegedAction()
{
public Object run()
{
return System.getProperty("user.home");
}
});
Has the user accepted full access for your applet in Safari? Sounds like the security manager kicking in.
I remember having a similar problem in an older version of Safari (this was years ago), and the solution I found was adding a delay to the applet. It seemed Safari for some reason was allowing the applet to run before the user was given the "trust this applet" dialogue (other browsers would not start the applet until after the user granted or denied access). At that point the applet was not trusted and a security exception would occur. Even though the user would then allow trust, it was too late as the applet had already run and failed. I had to add a delay for safari, so it would not try doing anything that needed secure access until a period of time had passed, allowing the user to give access before the applet tried doing anything needing security access.

Categories

Resources