JBAS-2237: Discussion
adrian.brock Sep 12, 2005 11:09 AM
Comment by Scott M Stark [09/Sep/05 12:13 PM] Delete
[ Permlink ]
The stack trace and message look consistent to me. You appear to have used an invalid naming url for the current InitialContextFactory and its parsing the host and port incorrectly because of this. Show the InitialContextFactory env/jndi.properties.
Comment by Jens Elkner [09/Sep/05 05:01 PM] Delete
[ Permlink ]
Hmmm - well, the detailed message of the execption says:
Could not obtain connection to any of these urls: https://localhost:8443/invoker/JNDIFactory and discovery failed with error: javax.naming.CommunicationException: Receive timed out [Root exception is java.net.SocketTimeoutException: Receive timed out]
BUT the stacktrace tells a DIFFERENT story ...
The naming URL is https://localhost:8443/invoker/JNDIFactory - so should be correct. NOTE: I'm not saying, that there shouldn't be a stacktrace, I'm just saying, that the detailed message and the stacktrace do NOT correlate.
I guess, the first stacktrace (the real reason) is swallowed up and than more or less sensless stuff tried (which might be a security issue), and finally the last stacktrace of the senseless stuff gets thrown with the initial stacktrace.toString() as message... More than strange!!!
Comment by Adrian Brock [09/Sep/05 06:25 PM] Delete
[ Permlink ]
I've changed this to a feature request.
This is better than it was before. Previously you would just get a message "lookup failed: received timeout"
and who knows how many times that has been posted in the forums?
We could have a policy that "complicated stuff" only gets put in the logs, but since it is too late
after the fact to enable logging that doesn't always work. And a lot users don't even seem to be
aware that logging exists.
What you are seeing is multiple errors caused by the different mechanisms JBoss jndi tries to connect.
1) Using the provider url(s)
2) Using hajndi discovery
All failed so you get multiple errors, with the stacktrace from the first (and probably the most pertinent
since that it was what trying to use) error.
It is a feature request because it could be better formatted. It certainly isn't a bug.
If you don't want to expose your users to the "real reason" it is trivial to do
try
{
object = context.lookup("blah");
}
catch (NamingException e)
{
mylog.log("real error looking up blah", e);
throw new NamingException("cannot lookup blah");
}
Comment by Adrian Brock [09/Sep/05 06:31 PM] Delete
[ Permlink ]
"Show the InitialContextFactory env/jndi.properties."
Do this in the forums, not here.
Comment by Jens Elkner [10/Sep/05 05:02 PM] Delete
[ Permlink ]
> This is better than it was before. Previously you would just get a message
> "lookup failed: received timeout" and who knows how many times that has been posted > in the forums?
Hmmm, not sure, whether we are on the same subject. It is completely ok, to wrap an exception into another with a more descriptive message. What is not ok, is, to throw an unrelated Exception, with the description of a completely different Exception.
The point is, the provider URL is in this example https://localhost:8443/invoker/JNDIFactory . This causes a receive timout exception, e.g. because the service is not running. So the thrown Exception stack should be
...
javax.naming.CommunicationException: Unable to connect to localhost:8443
java.net.SocketTimeoutException: Receive timed out
In this case, the application designer is able to analyze the correct cause (timeout) and given an appropriate hint to the user (e.g. "make sure, 1) that the service is running, 2) you entered the correct hostname, 3) you entered the correct port", etc).
If the root cause would be an UnknownHostException, one could warn: "Unable to resolve the hostname 'e.getMessage()'."
With the current exception chaos wrt. the example, one would always get "Unable to resolve the hostname 'https'." - which is obviously totaly brain damaged.
Analyzing the detailedMessage is no option, since nobody knows, whatever will show up there (now or in future). So the only thing is the real exception stack, one can rely on and BTW: not all end users are able to read/understand english - so there is a need for i18n and since the jboss doesn't do that (which is IMHO acceptable), the app developer must do the additional work. But than (again) he needs something reliable.
IMHO jboss tries to do too much and thats why things get screwed up - since it does not know, what the application wants to do and makes wrong assumptions...
Actually, I can't see any reason, why jboss tries to connect to a host 'https'. The Provider URL is https://localhost:1099/invoker/JNDIFactory -
clearly: the scheme is 'https', the host is 'localhost', the port is '1099', the path '/invoker/JNDIFactory'. So, what is unclear here or can not be understood ?
IMHO, it is easy to parse the provided URL into an URI and extract all required parts. If the scheme is missing, one can throw a Maleformed URL exception. If there is no host, well throwing an exception or using a default would be ok. If port is -1, use the default. And (which would be IMHO already too much), if scheme is http[s] and part is null, one could set the part automatically to /invoker/JNDIFactory.
And finally, if an URI with all required parts has been constructed, one can try to connect. If this fails, the exception is wrapped into a NamingExcpetion (or CommunicationException) and rethrown. That's it - straightforward, simple and reliable. No need to try other (unsecure) stuff, which the developer actually had never in mind!
Comment by Jens Elkner [10/Sep/05 05:05 PM] Delete
[ Permlink ]
> All failed so you get multiple errors, with the stacktrace from the first (and probably the > most pertinent
> since that it was what trying to use) error.
And this is actually really a bug, you get the message from the first, but the stacktrace from the last!!!
Comment by Jens Elkner [10/Sep/05 07:16 PM] Delete
[ Permlink ]
Couldn't resist to have a look at the mess:
e.g. jnp://localhost:1100 (wrong port)
org.jnp.naming.interfaces.NameingContext#checkRef(props):
...
// get server
servex =
javax.naming.CommunicationException: Failed to connect to server localhost:1100
javax.naming.ServiceUnavailableException: Failed to connect to server localhost:1100
java.net.ConnectException:Connection refused
// discover server
discoveryFailure =
javax.naming.CommunicationException: Receive timed out
java.net.SocketTimeoutException: Receive timed out
// throws
new CommunicationException("Could not obtain connection to any of these urls: localhost:1100 and discovery failed with error: javax.naming.CommunicationException: Receive timed out [Root exception is java.net.SocketTimeoutException: Receive timed out]", serverex)
So in this case, the exception stack is right, but the detailed message of the ComEx doesn't even mention the cause for the given provided URL (which is 'connection refused').
E.g. http://localhost:8081/invoker/JNDIFactory (wrong port)
org.jboss.naming.HttpNamingContextFactory#getInitialContext(props):
...
ex = java.net.ConnectException: Connection refused
throw new NamingException("Failed to retrieve Naming interface", ex)
So the exception stack is right, but the detailed message doesn't mention the real cause ('connection refused') - next case, where detailed message is unusable for an enduser.
E.g. https://localhost:8443/invoker/JNDIFactory (wrong factory (NamingContextFactory) and services is not running)
org.jnp.naming.interfaces.NameingContext#checkRef(props)
...
/* IMHO #parseNameForScheme(...) should throw an exception, since it doesn't know
anything about 'https:', which - if ignored - in turn leads to wrong values for the
subsequent methods (e.g. host = https - aha!, and sets the port to 1099 - oops! -
nobody said that, we said 8443!)
*/
// get server
serverex =
javax.naming.CommunicationException: Failed to connect to server https:1099
javax.naming.ServiceUnavailableException: Failed to connect to server https:1099
java.net.UnknownHostException: https: https
// discover server
discoveryFailure =
javax.naming.CommunicationException: Receive timed out
java.net.SocketTimeoutException: Receive timed out
// throws
new CommunicationException("Could not obtain connection to any of these urls: https://localhost:8443/invoker/JNDIFactory and discovery failed with error: javax.naming.CommunicationException: Receive timed out [Root exception is java.net.SocketTimeoutException: Receive timed out]", serverex)
So again, we get a detailed message, which is unusable for the enduser. But I must admit, that the provided exception stack is correct (in opposite, what I assumed earlier).
So perhaps the RFE should be, throw an Exception, if there is scheme in the provided URL, which isn't known by jboss handler. And well, at least IMHO the default auto-discovery is quite questionable ...