wood burning stoves 2.0*
The moose likes Distributed Java and the fly likes Error in setting SecureRMIClientSocketFactory Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Distributed Java
Bookmark "Error in setting SecureRMIClientSocketFactory" Watch "Error in setting SecureRMIClientSocketFactory" New topic
Author

Error in setting SecureRMIClientSocketFactory

Larry Grieve
Greenhorn

Joined: Apr 05, 2010
Posts: 6
I am working on an application from a vendor that requires me to use JRE version 1.5.0_14 on my client PC with MS IE 7.0, I have also updated to the latest Java 1.6.0_16.

I have this application configured to use SSL for HTTPS per the procedure the vendor requires on their server. When I attempt to launch their application using HTTPs, then it launches JRE. I get the login window then it tries to connect to the Java application then I get the error "RMI connection unavailable between client and serer possibly due to port 1099 conflict". I have made sure all firewalls that we have are ok for ports 1098 and 1099 for RMI.

I get the following from the Java console output when I try to get in via HTTPS:

Error in setting SecureRMIClientSocketFactory.
java.net.SocketException: factory already defined
at java.rmi.server.RMISocketFactory.setSocketFactory(Unknown Source)
at com.acme.launcher.AcmeCustomClientFrame$3.run(AcmeCustomClientFrame.java:469)

The interesting thing is that when I configure the server to use HTTP I have no issues with JRE and RMI. I cannot find anything on the web that tells me anything about the SecureRMIClientSocketFactory and the factory already being defined.

I will mention that my company uses a proxy and we have identified this proxy is causing this issue with the JRE RMI with SSL. I have found that if I go directly to the Java Control panel to the Network Settings section to set this to "Direct connect" instead of "Use browser settings" I do not get the error. The proxy engineer from my company is stating "The java plug-in in use by Qwest browsers, and required by ACME-EMS is not parsing the Auto proxy configuration file correctly, the plug-in is using the proxy servers identified in the auto config file for every transaction, ignoring logic within the autoconfig file to exempt internal Qwest addresses from proxy eligibility. The plug-in is failing to load code thru the proxy servers while in https mode, generating an internal error and halting. This operations works in http mode, but not in https mode."

Can anybody please help me on what the issue may be here ?

Thanks
Larry
Karthik Shiraly
Ranch Hand

Joined: Apr 04, 2009
Posts: 497
    
    5
Hi Larry,

I'm not very clear about the components in your system (esp. the part about browsers), but if it's possible to add a VM argument to enable logging on the RMI client and/or server, some differences in RMI logs between working and nonworking setup may throw some more light.

Is this stack trace all there is, or are there some root cause exceptions below?

Cheers
Karthik
Larry Grieve
Greenhorn

Joined: Apr 05, 2010
Posts: 6
Karthik,

The browser is Microsoft Internet Explorer 7.0. The only stack trace I have been able to capture is from the Java console with the following enabled for Debugging; Enable tracing, Enable logging and, Show applet lifecycle exceptions. I have Java console set to "Show console".

I am very green when it comes to Java. I am not sure what you mean to enable logging on the RMI client and/or server. If you may be so kind as to tell me how to enable RMI logging, if this is seperate from the Java console, please provide the steps on how to perform this.

I believe I can attach the entire Java console output if you would like to see that. Any and all help will be greatly appreciated.

Thanks
Larry
Karthik Shiraly
Ranch Hand

Joined: Apr 04, 2009
Posts: 497
    
    5
Hi Larry,

The picture I get is: Client side is a browser java applet which is started when you enter some URL (hosted on the Acme-EMS server). Applet shows a login form. If the URL entered is a https://, there's an exception; but if it's setup to be http://, everything works. Is this correct?
Where does the 'Qwest' browser fit in?

If it's an applet, then I'll have to experiment how to enable logging - never done it before. Will post you the steps tomorrow.

Meanwhile, if you could put up the entire console output, it may help.

Cheers
Karthik
Larry Grieve
Greenhorn

Joined: Apr 05, 2010
Posts: 6
Karthik,

You are correct for your browser java applet information.

As for the "Qwest" browser, please disregard "Qwest". I work for a company named "Qwest". The browser we have to use is Microsoft Internet Explorer 7.0 (MS IE7.0). The client side is the MS IE 7.0 browser java applet which as you stated is started when you enter the applicable URL for the web server that I call the Acme-EMS. The URL applet launches a login form. When I complete the login information and click "Login" the application loads then before it completes the loading I get the "RMI connection unavailable between client and serer possibly due to port 1099 conflict" error. I will also mention I get this same error if I try to use Mozilla Firefox.

I have tried to attach the entire console output but this site will not allow .doc or .txt files to be attached. So not to clutter too much I am providing the below console output to the point I get the errors. Then after that I get a bunch more information. The application on the server finishes the launch but everytime I click on something I get the error "Failed to communicate with remote server".

Java Web Start 1.6.0_16
Using JRE version 1.6.0_16-b01 Java HotSpot(TM) Client VM
User home directory = C:\Documents and Settings\grievel
----------------------------------------------------
c: clear console window
f: finalize objects on finalization queue
g: garbage collect
h: display this help message
m: print memory usage
o: trigger logging
p: reload proxy configuration
q: hide console
r: reload policy configuration
s: dump system and deployment properties
t: dump thread list
v: dump thread stack
0-5: set trace level to <n>
----------------------------------------------------
Reading certificates from 11 https://ltv1apem01.qintra.com:8443/acmePacketEMS/classes/AcmeClientLauncher.jar | C:\Documents and Settings\grievel\Application Data\Sun\Java\Deployment\cache\6.0\1\5fc71881-2b8fc0e6.idx
Note no disclaimer file found. Reason : https://ltv1apem01.qintra.com:8443/servlets/../conf/disclaimer.txt
Reading certificates from 11 https://ltv1apem01.qintra.com:8443/classes/NmsClientClasses.jar | C:\Documents and Settings\grievel\Application Data\Sun\Java\Deployment\cache\6.0\26\529e35da-203365d7.idx
Reading certificates from 11 https://ltv1apem01.qintra.com:8443/acmePacketEMS/classes/acmePacketEMSClient.jar | C:\Documents and Settings\grievel\Application Data\Sun\Java\Deployment\cache\6.0\31\14dbacdf-53291741.idx
Reading certificates from 11 https://ltv1apem01.qintra.com:8443/classes/AdventNetProBeans.jar | C:\Documents and Settings\grievel\Application Data\Sun\Java\Deployment\cache\6.0\53\4e755bf5-1beaee9c.idx
Reading certificates from 11 https://ltv1apem01.qintra.com:8443/classes/ApiUtils.jar | C:\Documents and Settings\grievel\Application Data\Sun\Java\Deployment\cache\6.0\39\345ea627-7620cf57.idx
Reading certificates from 11 https://ltv1apem01.qintra.com:8443/classes/AdventNetSnmp.jar | C:\Documents and Settings\grievel\Application Data\Sun\Java\Deployment\cache\6.0\6\2fc3f106-3c42851a.idx
Reading certificates from 11 https://ltv1apem01.qintra.com:8443/classes/crimson.jar | C:\Documents and Settings\grievel\Application Data\Sun\Java\Deployment\cache\6.0\56\26a43b38-6e4e6ad7.idx
Reading certificates from 11 https://ltv1apem01.qintra.com:8443/classes/JimiProClasses.zip | C:\Documents and Settings\grievel\Application Data\Sun\Java\Deployment\cache\6.0\27\776cf51b-50cf17cd.idx
Instantiated main scheduler with 4 threads
scheduler initialized
inside initConfProperties() url = https://ltv1apem01.qintra.com:8443/acmePacketEMS/conf/comMode.conf
comMode.conf URL path https://ltv1apem01.qintra.com:8443/acmePacketEMS/conf/comMode.conf
Registering for responses GENERIC_ID
Completed initConfProperties()
truststorePath = C:\Program Files\Java\jre1.6.0_16\lib\security\Truststore.truststore
keystorePath = C:\Program Files\Java\jre1.6.0_16\lib\security\PrimaryTrans.key
Error in setting SecureRMIClientSocketFactory.
java.net.SocketException: factory already defined
at java.rmi.server.RMISocketFactory.setSocketFactory(Unknown Source)
at com.acme.launcher.AcmeCustomClientFrame$3.run(AcmeCustomClientFrame.java:469)
In InOutOptionsUtility

Thanks
Larry
Karthik Shiraly
Ranch Hand

Joined: Apr 04, 2009
Posts: 497
    
    5
Hi Larry,

Took me a while to figure out applet logging. Here are the steps you should do on the client machine where browser runs:

1. First backup the file C:\Program Files\Java\jre1.6.0_16\lib\logging.properties, so that system can be reverted back later.
2. Open C:\Program Files\Java\jre1.6.0_16\lib\logging.properties with any text editor.
3. You'll most likely see something like this:


4. Make the highlighted changes. fyi, # comments out the line. Note that in some lines # is inserted and in others it's removed :
...
#handlers= java.util.logging.ConsoleHandler

# To also add the FileHandler, use the following line instead.
handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers. For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= FINEST

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################

# default file output is in user's home directory.
java.util.logging.FileHandler.level=FINEST
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 10000000
java.util.logging.FileHandler.count = 1
#java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = FINEST
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter


############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################

# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE


5. Clear the browser cache and open https:// URL.
If the changes have been done correctly, then you should see java console spew out a lot of messages with prefixes like "FINE:...", "FINEST:...".
You should also see a file 'C:\Documents and Settings\grievel\java0.log' created. Do login and other actions till you can't proceed any further due to errors. Then shutdown the browser, make a copy of 'C:\Documents and Settings\grievel\java0.log' somewhere else and delete it.

6. Repeat with the http://URL.

7. Upload the two java0.log files you get, along with the latest .trace files under 'C:\Documents and Settings\grievel\Application Data\Sun\Java\Deployment\log'.

8. Finally, revert back to the original logging.properties.

These symptoms may tell us something more (certainly not guaranteed, just hope for the best!).

Cheers
Karthik
Larry Grieve
Greenhorn

Joined: Apr 05, 2010
Posts: 6
Karthik,

Thanks and I performed the steps like you asked. The issue is that the size of the java0.log files are 9 Meg per file. Then the .trace files are 9 Meg as well per file. This site only allows 3 files with a max total size of 1024 kb so these files are too big to upload. If there is another way for me to get you these files please let me know. I am sure that if I Winzip them they will still be too big to upload.

There is a lot of information in these files, if I only knew what i was looking at.

Thanks
Larry
Karthik Shiraly
Ranch Hand

Joined: Apr 04, 2009
Posts: 497
    
    5
Hi Larry,

You can upload them to any of the file sharing sites maybe - rapidshare, megaupload, something like that - and post the link here (or as a private message).

What I would look for in these trace files is any action related to RMI (any message containing java.rmi....).
Your post mentions about code downloading working in one case and not in another; I'm assuming the person is referring to RMI code downloading, so I'd look for exceptions related to that, to check if the statement is valid and whether proxy configuration is really the cause.
I'd try and spot some difference between the two cases, basically.
Also, due to shortcomings of logging, majority of the traces in these files are actually related to swing UI actions; I'd use a text editor like Textpad to dispose off these useless traces, and concentrate on the traces related to communication.

Cheers
Karthik
Larry Grieve
Greenhorn

Joined: Apr 05, 2010
Posts: 6
Karthik,

Thanks for the file sharing sites. Here is what I have:

HTTP Files
http://rapidshare.com/files/373135600/javaws8624585419295541205.log.html (947 kb)
http://rapidshare.com/files/373138532/javaws5232675018360145200.trace.html (9428 kb)
http://rapidshare.com/files/373142975/java0.log.html (9401 kb)

HTTPS Files
http://rapidshare.com/files/373144377/java0.log.html (8941 kb)
http://rapidshare.com/files/373146215/javaws1094668102751770378.trace.html (9009 kb)
http://rapidshare.com/files/373146778/javaws6543014904386574156.log.html (417 kb)

I hope you are able to download these files. Please let me know if there is any more information I can provide to help understand this issue.

Thanks
Larry
Karthik Shiraly
Ranch Hand

Joined: Apr 04, 2009
Posts: 497
    
    5
Hi Larry,

I was able to reproduce the same error locally and can confirm that it's the proxy setting in java control panel that's the root cause. The problem is same as this Sun problem report.

To understand why it happens, I have to explain little about RMI.
A frequent complaint cited against all the common distributed technologies - RMI, CORBA, DCOM - is that firewalls typically block their communications.
Sun anticipated this problem and provided for HTTP tunneling for RMI - i.e, RMI communication can be wrapped in HTTP packets, since HTTP is usually allowed by firewalls.
The important point to note is, this HTTP tunneling is engaged when a proxy server is specified. Same applies for HTTPS.
This article explains it well.
RMI uses the concept of socket factories to set up the tunneling.
The socket factories concept is also needed if the network transport needs to be customized - for example, running RMI over SSL connections.

In the SSL case with proxy configured, the java web start plugin detects that there is a proxy and installs a socket factory that can do tunneling.
The Acme client app then runs, downloads a file 'comMode.conf' and realises it should use SSL encrypted RMI.
So it tries to install its own custom socket factory that provides RMI over SSL, using the 'RMISocketFactory.setSocketFactory()' method and fails.
It fails because once the VM-wide socket factory has been set, it can't be changed.
It looks like the app has been designed to continue even if this fails.
So, we now have a client that has been unable to setup RMI over SSL, and has fallen back to using unencrypted RMI.
But on the other end, the server is probably ok and expecting encrypted RMI communication.
The two don't understand each others data, and that's why so many 'non-JRMP server at remote endpoint' errors, null remote object references and code download errors (as observed by the proxy engineer) are seen in the https trace file.

In the SSL case without proxy, the java web start plugin detects no proxy and doesn't first install a socket factory for tunneling.
That's why Acme client app's attempt to install one succeeds and it's able to proceed normally.

In the non-SSL unencrypted case without proxy, the java web start plugin detects no proxy and doesn't first install a socket factory for tunneling.
That's why Acme client app's attempt succeeds and it's able to proceed normally.

In the non-SSL unencrypted case with proxy, the java web start plugin will install a socket factory for tunneling.
But the Acme client app will not attempt to install its own socket factory (attempt is made only if comMode.conf specifies SSL),
and so it's able to proceed normally.

Solutions:
- I feel this is a bug in Acme client app. It should anticipate that a VM-wide socket factory may already have been installed, and should be changed to use the per-remote-object RMIServerSocketFactory and RMIClientSocketFactory facility described in the problem report. This approach worked in my experiments.

- As workarounds for you, one of these may work:
- Set Java control panel to always use browser settings, and specify proxy configuration file only in browser.
- Set Java control panel to always use direct connection, if server is local server.
- Unset the proxy host setting at runtime by setting '-Ddeployment.proxy.http.host=' in the Java Control Panel > Java > View > Runtime Parameters column. Note that this setting will override for all java web start apps and applets.

Cheers
Karthik

Larry Grieve
Greenhorn

Joined: Apr 05, 2010
Posts: 6
Karthik,

Thank you very much for all your indepth information and work on reproducing this issue. I will take all this information back to the vendor and get them to fix it from their side. I know they are looking to go to a Thin-Web client instead of using JRE so maybe they already knew something was not right, but the Thin-Web client does not come out until later this year. I need to do more research on Thin-Web client as well.

Thank you again for all of your help to understand this issue and provide all the information that you have. Greatly appreciate it.

Thanks
Larry
Karthik Shiraly
Ranch Hand

Joined: Apr 04, 2009
Posts: 497
    
    5
You're welcome ! Thank you too for posting the problem, since it made me go much deeper into RMI than I usually do, and pick up some new knowledge.
Viji Venkatraman
Greenhorn

Joined: Jul 08, 2010
Posts: 4
Hi Karthik

Firstly,let me appreciate you for your in-depth analysis of this Java Webstart problem on creating an explicit SocketFactory. This has typically helped in solving a similar issue which was raised by one of our customers. However, I would like some clarifications on the below points:

1. I presume, both ClientSocketFactory and ServerSocketFactory will be created in the server side only.But the when I export an object using these socket factories and I try to obtain a handle for the same from the client side , inturn the ClientSocketFactory which is created in the server side creates a socket which is used for RMI communication with the server. But the missing point is how does this happen? How does the client know that this particular remote object has a SocketFactory associated with it? I have not been able to deduce this part .

2. Have you done some kind of testing to ensure that if objects are exported using socket factories , one can do a Naming.lookup on the object from Java Webstart client connected to the server in https mode via proxy? If yes, can you please elaborate a little more on your findings.

Hoping to receive a quick reply.

Thanks in Advance.

Vg
Karthik Shiraly
Ranch Hand

Joined: Apr 04, 2009
Posts: 497
    
    5
Hi Viji

1. I presume, both ClientSocketFactory and ServerSocketFactory will be created in the server side only.But the when I export an object using these socket factories and I try to obtain a handle for the same from the client side , inturn the ClientSocketFactory which is created in the server side creates a socket which is used for RMI communication with the server. But the missing point is how does this happen? How does the client know that this particular remote object has a SocketFactory associated with it? I have not been able to deduce this part .


The custom client and socket factories are passed via the UnicastRemoteObject constructor. Notice that both are Serializable too. Check the source code of java.rmi.server.UnicastRemoteObject and you'll see both are its private members.
When client does a lookup, one of the classes downloaded to client side is the custom client socket factory class (since it's a member of the remote object).
The RMI system classes, not your client, then use the custom client socket factory, if it's set, to create the socket. All this happens inside the lookup() call.
Switch on FINEST level logging for your client, and you'll see this flow. Here's a typical trace:



2. Have you done some kind of testing to ensure that if objects are exported using socket factories , one can do a Naming.lookup on the object from Java Webstart client connected to the server in https mode via proxy? If yes, can you please elaborate a little more on your findings.

You mean using SSL capable custom socket factories? No, not specifically. I explored using just a dummy custom factory, because it was enough for this issue - it was more about setting the factory itself, not what happens after it.
But I remember the Sun RMI tutorials included an SSL based secure RMI example - perhaps you can check that out.
 
Consider Paul's rocket mass heater.
 
subject: Error in setting SecureRMIClientSocketFactory