diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/YarnClientImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/YarnClientImpl.java index e406862..b4f84a7 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/YarnClientImpl.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/YarnClientImpl.java @@ -369,13 +369,26 @@ private void addTimelineDelegationToken( } } return timelineClient.getDelegationToken(timelineDTRenewer); - } catch (Exception e) { + } catch (Throwable e) { if (timelineServiceBestEffort) { LOG.warn("Failed to get delegation token from the timeline server: " + e.getMessage()); return null; } - throw e; + if(e instanceof NoClassDefFoundError) { + NoClassDefFoundError classNotFoundError = + new NoClassDefFoundError(e.getMessage() + + ". It appears that the timeline client " + + "failed to initiate because an incompatible dependency " + + "in classpath. If timeline service is optional to this " + + "client, try to work around by setting " + + YarnConfiguration.TIMELINE_SERVICE_CLIENT_BEST_EFFORT + + " to true."); + classNotFoundError.setStackTrace(e.getStackTrace()); + throw classNotFoundError; + } else { + throw e; + } } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestYarnClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestYarnClient.java index 240f31c..be96fff 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestYarnClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestYarnClient.java @@ -156,6 +156,36 @@ public void testClientStop() { } @Test + public void testStartTimelineClientWithNoClassFoundFailure() + throws Exception { + Configuration conf = new Configuration(); + conf.setBoolean(YarnConfiguration.TIMELINE_SERVICE_ENABLED, true); + YarnClient client = YarnClient.createYarnClient(); + if (client instanceof YarnClientImpl) { + YarnClientImpl impl = (YarnClientImpl) client; + YarnClientImpl spyClient = spy(impl); + // Create timeline client might fail if client has an + // incompatible library in classpath, e.g Jersey. + when(spyClient.createTimelineClient()).thenThrow( + new NoClassDefFoundError("Mock a NoClassDefFoundError.")); + spyClient.init(conf); + spyClient.start(); + try { + spyClient.getTimelineDelegationToken(); + } catch (NoClassDefFoundError e) { + // Verify NoClassDefFoundError is handled + // it is wrapped with a better error message, which mentions + // timeline client best effort property as a work around + Assert.assertTrue(e.getMessage() != null && + e.getMessage().contains( + YarnConfiguration.TIMELINE_SERVICE_CLIENT_BEST_EFFORT)); + } finally { + spyClient.stop(); + } + } + } + + @Test public void testStartWithTimelineV15Failure() throws Exception{ Configuration conf = new Configuration(); conf.setBoolean(YarnConfiguration.TIMELINE_SERVICE_ENABLED, true);