6 Replies Latest reply: Feb 24, 2012 12:59 PM by EJP RSS

    spaces in URL causes "java.net.MalformedURLException: no protocol: "

    919255
      Hi all,

      i've got a Problem using RMI. Following exception is thrown:

           java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
           java.net.MalformedURLException: no protocol: xxx.

      Cause of this error is an URLClassLoader of an external application using my JDBC-Driver which connects to my server via RMI. The URLClassLoader (got by class.getClassLoader()) contains at first position in the array an URL representing a jarfile by absoulte path, containing whitespaces. This URL seems to be set by the extern application to the classpath with these whitespaces. I do not know where and how to change it.
      I thought of a solution of this problem to manipulate ClassLoader to replace all containing white spaces in the URLs with the correct syntax for URLs: %20.
      In the first try, i used system-property "java.rmi.server.codebase" to set the correct codebase with replaced spaces. This seems not to work. The codebase-property seems to be used by RMIClassLoader (i short look to the code shows, that codebase-property is only used if the current classloader is also a system classloader?).
      Second try was to create an own URLClassLoader with correct URL-Strings. But i do not know how to use it for RMI. Using my correct URLClassLoader for my class instance with following code:

      final URL[] urLs = ((URLClassLoader) cl.getClassLoader()).getURLs();
      final URL[] newUrls = new URL[urLs.length];
      int i = 0;
      for (final URL url : urLs) {
      try {
      newUrls[i] = new URL(url.toExternalForm().replace(" ", "%20"));
      } catch (final MalformedURLException e) {
      LOG.error("An error occurred, cause is: " + e.getMessage(), e);
      }
      i++;
      }
      loader = new URLClassLoader(newUrls, originalClassLoader);
      final Class<?> clazz = loader.loadClass("MyDriver");
      final Object instance = clazz.newInstance();

      does not work. Do you know how i can use this classloader instead of the original classloader to solve my problem with white spaces in URLs?

      Many thanks in advance!
        • 1. Re: spaces in URL causes "java.net.MalformedURLException: no protocol: "
          tschodt
          916252 wrote:
          Subject: Re: spaces in URL causes "java.net.MalformedURLException: no protocol: "

          i've got a Problem using RMI. Following exception is thrown:
               java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
               java.net.MalformedURLException: no protocol: xxx.
          "no protocol" typically means it is not a URL;
          it does not start with "http://" or "ftp://" or "file:///", or ...
          Cause of this error is an URLClassLoader of an external application using my JDBC-Driver which connects to my server via RMI. The URLClassLoader (got by class.getClassLoader()) contains at first position in the array an URL representing a jarfile by absoulte path, containing whitespaces. This URL seems to be set by the extern application to the classpath with these whitespaces. I do not know where and how to change it.
          I thought of a solution of this problem to manipulate ClassLoader to replace all containing white spaces in the URLs with the correct syntax for URLs: %20.
          In the first try, i used system-property "java.rmi.server.codebase" to set the correct codebase with replaced spaces. This seems not to work. The codebase-property seems to be used by RMIClassLoader (i short look to the code shows, that codebase-property is only used if the current classloader is also a system classloader?).
          Second try was to create an own URLClassLoader with correct URL-Strings. But i do not know how to use it for RMI. Using my correct URLClassLoader for my class instance with following code:
          final URL[] urLs = ((URLClassLoader) cl.getClassLoader()).getURLs();
          final URL[] newUrls = new URL[urLs.length];
          int i = 0;
          for (final URL url : urLs) {
          try {
          newUrls[i] = new URL(url.toExternalForm().replace(" ", "%20"));
          } catch (final MalformedURLException e) {
          LOG.error("An error occurred, cause is: " + e.getMessage(), e);
          }
          i++;
          }
          loader = new URLClassLoader(newUrls, originalClassLoader);
          final Class<?> clazz = loader.loadClass("MyDriver");
          final Object instance = clazz.newInstance();
          does not work. Do you know how I can use this classloader instead of the original classloader to solve my problem with white spaces in URLs?
          Using RMI - is the offending classloader even in the same process (or even on the same system)?
          To use a classloader different from the system classloader
          make sure your classes are not on the system classloader classpath,
          use the system classloader to load your custom classloader
          and use your custom classloader instance to load the "root class" of the classes you are concerned about,
          the rest of the classes will be loaded using the same classloader
          assuming they are not avaliable on the system classloader classpath.
          • 2. Re: spaces in URL causes "java.net.MalformedURLException: no protocol: "
            EJP
            The URLClassLoader (got by class.getClassLoader()) contains at first position in the array an URL representing a jarfile by absoulte path, containing whitespaces. This URL seems to be set by the extern application to the classpath with these whitespaces. I do not know where and how to change it.
            Back up a little. Who is using this URL and for what purpose? What operation is being performed when the exception is thrown?
            I used system-property "java.rmi.server.codebase" to set the correct codebase with replaced spaces. This seems not to work.
            That property is set at a JVM that uses RMI to annotate objects being sent via RMI, so that the receiver knows where to load it from. Setting it at the receiver has no effect.
            • 3. Re: spaces in URL causes "java.net.MalformedURLException: no protocol: "
              919255
              Hi, many thanks for your replies.

              The URL, i detected in the URL-Array of the URLClassLoader, is not needed by my driver but seems to be set by the external application which is using my driver. The the exception is thrown by calling a method on the remote object. I'll give you more lines of the stack trace:

                   java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
                   java.net.MalformedURLException: no protocol: BusinessObjects
              java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
                   java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
                   java.net.MalformedURLException: no protocol: BusinessObjects
                   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:619)

              The space in the URL of the external application seems to be placed by an incorrect use of file.toURL() instead of file.toURI().toURL(). But as i said before, its not my application using it that way :(

              Concerning your replies i'll try to use my custom class loader correctly, in my opinion it is an nice way to prevent problems with spaces in URLs.
              Also the idea, setting a codebase on my server, sounds very good!

              Many thanks.
              • 4. Re: spaces in URL causes "java.net.MalformedURLException: no protocol: "
                EJP
                I think that is probably coming from an incorrect setting of java.rmi.server.hostname in the first place. If it was coming from anywhere else the guy that is setting it wouldn't work.
                • 5. Re: spaces in URL causes "java.net.MalformedURLException: no protocol: "
                  919255
                  great tip, many thanks :)

                  i set following properties of my server:

                  java.rmi.server.useCodebaseOnly=true
                  java.rmi.server.hostname=myhostname
                  java.rmi.server.codebase=correct URLs to the JAR-Files

                  and now connection was successful to my main server. I do also have an second server using rmi wich is contacted after connection to main server was successful. I've done the same property settings to the second server, but if a remote method called on the second server, the same exception is thrown... Both server are running in the same system, the jdbc-client also. Thats why i've set the same hostname to the second server. Do you know why this settings are working for mainserver and not for second?
                  • 6. Re: spaces in URL causes "java.net.MalformedURLException: no protocol: "
                    EJP
                    If a sent object already has a codebase annotation and was loaded from that codebase, the annotation won't be changed.