浏览代码

HADOOP-15984. Update jersey from 1.19 to 2.x. (#7019)

Co-authored-by: Akira Ajisaka <aajisaka@apache.org>
Co-authored-by: Viraj Jasani <vjasani@apache.org>
Co-authored-by: Ayush Saxena <ayushsaxena@apache.org>
Co-authored-by: PJ Fanning <fanningpj@apache.org>
Co-authored-by: Steve Loughran <stevel@apache.org>
Co-authored-by: He Xiaoqiao <hexiaoqiao@apache.org>
Reviewed-by: Steve Loughran <stevel@apache.org>
Reviewed-by: He Xiaoqiao <hexiaoqiao@apache.org>
Signed-off-by: Shilun Fan <slfan1989@apache.org>
slfan1989 3 月之前
父节点
当前提交
06d36f5a6a
共有 100 个文件被更改,包括 3756 次插入2915 次删除
  1. 21 7
      LICENSE-binary
  2. 2 0
      hadoop-client-modules/hadoop-client-check-invariants/pom.xml
  3. 5 1
      hadoop-client-modules/hadoop-client-check-invariants/src/test/resources/ensure-jars-have-correct-contents.sh
  4. 1 0
      hadoop-client-modules/hadoop-client-check-test-invariants/pom.xml
  5. 2 8
      hadoop-client-modules/hadoop-client-integration-tests/pom.xml
  6. 19 87
      hadoop-client-modules/hadoop-client-minicluster/pom.xml
  7. 19 7
      hadoop-client-modules/hadoop-client-runtime/pom.xml
  8. 0 76
      hadoop-client-modules/hadoop-client/pom.xml
  9. 0 12
      hadoop-cloud-storage-project/hadoop-cloud-storage/pom.xml
  10. 6 0
      hadoop-cloud-storage-project/hadoop-huaweicloud/pom.xml
  11. 1 1
      hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSBlockOutputStream.java
  12. 1 1
      hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSInputStream.java
  13. 2 2
      hadoop-common-project/hadoop-auth-examples/pom.xml
  14. 2 2
      hadoop-common-project/hadoop-auth/pom.xml
  15. 31 66
      hadoop-common-project/hadoop-common/pom.xml
  16. 25 9
      hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java
  17. 9 9
      hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java
  18. 4 5
      hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerLogs.java
  19. 10 5
      hadoop-common-project/hadoop-kms/pom.xml
  20. 0 1
      hadoop-common-project/hadoop-kms/src/main/conf/kms-log4j.properties
  21. 10 4
      hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java
  22. 1 1
      hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSExceptionsProvider.java
  23. 2 14
      hadoop-common-project/hadoop-kms/src/main/resources/webapps/kms/WEB-INF/web.xml
  24. 2 2
      hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
  25. 0 2
      hadoop-common-project/hadoop-kms/src/test/resources/log4j.properties
  26. 2 2
      hadoop-common-project/hadoop-nfs/pom.xml
  27. 5 0
      hadoop-hdfs-project/hadoop-hdfs-client/pom.xml
  28. 6 5
      hadoop-hdfs-project/hadoop-hdfs-httpfs/pom.xml
  29. 1 1
      hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/server/HttpFSExceptionProvider.java
  30. 0 2
      hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/server/HttpFSParametersProvider.java
  31. 24 21
      hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/server/HttpFSServer.java
  32. 4 10
      hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/lib/wsrs/JSONMapProvider.java
  33. 23 44
      hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/lib/wsrs/ParametersProvider.java
  34. 3 15
      hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/resources/webapps/webhdfs/WEB-INF/web.xml
  35. 3 15
      hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/webapp/WEB-INF/web.xml
  36. 1 2
      hadoop-hdfs-project/hadoop-hdfs-httpfs/src/test/java/org/apache/hadoop/fs/http/server/TestHttpFSServer.java
  37. 0 1
      hadoop-hdfs-project/hadoop-hdfs-httpfs/src/test/resources/default-log4j.properties
  38. 5 5
      hadoop-hdfs-project/hadoop-hdfs-nfs/pom.xml
  39. 5 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/pom.xml
  40. 0 3
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterWebHdfsMethods.java
  41. 19 5
      hadoop-hdfs-project/hadoop-hdfs/pom.xml
  42. 2 2
      hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/web/webhdfs/ExceptionHandler.java
  43. 22 5
      hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNodeHttpServer.java
  44. 242 43
      hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/web/resources/NamenodeWebHdfsMethods.java
  45. 57 46
      hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/web/ParamFilter.java
  46. 9 2
      hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/web/resources/ExceptionHandler.java
  47. 0 2
      hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/web/resources/TokenServiceParam.java
  48. 8 27
      hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/web/resources/UserProvider.java
  49. 5 5
      hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/web/TestWebHdfsFileSystemContract.java
  50. 0 4
      hadoop-hdfs-project/hadoop-hdfs/src/test/resources/log4j.properties
  51. 44 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/pom.xml
  52. 4 4
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/jobhistory/JobHistoryEventHandler.java
  53. 27 1
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/client/MRClientService.java
  54. 15 4
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AMWebApp.java
  55. 8 3
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AMWebServices.java
  56. 2 5
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/App.java
  57. 5 10
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/JAXBContextResolver.java
  58. 37 8
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebApp.java
  59. 118 127
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServices.java
  60. 73 72
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesAttempt.java
  61. 120 126
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesAttempts.java
  62. 58 66
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesJobConf.java
  63. 213 221
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesJobs.java
  64. 211 216
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesTasks.java
  65. 5 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-common/pom.xml
  66. 20 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/pom.xml
  67. 30 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/pom.xml
  68. 38 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java
  69. 0 4
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsWebApp.java
  70. 24 10
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsWebServices.java
  71. 4 6
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/JAXBContextResolver.java
  72. 117 136
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServices.java
  73. 119 138
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesAttempts.java
  74. 54 66
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesJobConf.java
  75. 214 254
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesJobs.java
  76. 225 246
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesJobsQuery.java
  77. 141 257
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesLogs.java
  78. 399 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesLogsExtend.java
  79. 217 229
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesTasks.java
  80. 103 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/reader/ContainerLogsInfoMessageBodyReader.java
  81. 88 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/reader/RemoteLogPathsMessageBodyReader.java
  82. 21 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/pom.xml
  83. 20 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-nativetask/pom.xml
  84. 5 0
      hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-shuffle/pom.xml
  85. 7 2
      hadoop-mapreduce-project/hadoop-mapreduce-client/pom.xml
  86. 7 2
      hadoop-mapreduce-project/hadoop-mapreduce-examples/pom.xml
  87. 79 110
      hadoop-project/pom.xml
  88. 20 0
      hadoop-tools/hadoop-archive-logs/pom.xml
  89. 20 0
      hadoop-tools/hadoop-archives/pom.xml
  90. 20 0
      hadoop-tools/hadoop-aws/pom.xml
  91. 21 0
      hadoop-tools/hadoop-azure-datalake/pom.xml
  92. 22 3
      hadoop-tools/hadoop-azure/pom.xml
  93. 20 0
      hadoop-tools/hadoop-datajoin/pom.xml
  94. 20 0
      hadoop-tools/hadoop-distcp/pom.xml
  95. 20 0
      hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-blockgen/pom.xml
  96. 20 0
      hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-infra/pom.xml
  97. 20 0
      hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-workload/pom.xml
  98. 20 0
      hadoop-tools/hadoop-extras/pom.xml
  99. 20 0
      hadoop-tools/hadoop-federation-balance/pom.xml
  100. 20 0
      hadoop-tools/hadoop-fs2img/pom.xml

+ 21 - 7
LICENSE-binary

@@ -363,7 +363,17 @@ org.xerial.snappy:snappy-java:1.1.10.4
 org.yaml:snakeyaml:2.0
 org.wildfly.openssl:wildfly-openssl:2.1.4.Final
 software.amazon.awssdk:bundle:2.25.53
-
+org.glassfish.jersey.core:jersey-common:2.46
+org.glassfish.jersey.core:jersey-server:2.46
+org.glassfish.jersey.inject:jersey-hk2:2.46
+org.glassfish.jersey.core:jersey-client:2.46
+org.glassfish.jersey.test-framework:jersey-test-framework-core:2.46
+org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-grizzly2:2.46
+org.glassfish.jersey.containers:jersey-container-servlet:2.46
+org.glassfish.jersey.containers:jersey-container-servlet-core:2.46
+org.glassfish.jersey.media:jersey-media-json-jettison:2.46
+org.glassfish.jersey.media:jersey-media-jaxb:2.46
+net.jodah:failsafe:2.4.4
 
 --------------------------------------------------------------------------------
 This product bundles various third-party components under other open source
@@ -498,12 +508,6 @@ org.slf4j:slf4j-reload4j:1.7.36
 CDDL 1.1 + GPLv2 with classpath exception
 -----------------------------------------
 
-com.github.pjfanning:jersey-json:1.22.0
-com.sun.jersey:jersey-client:1.19.4
-com.sun.jersey:jersey-core:1.19.4
-com.sun.jersey:jersey-guice:1.19.4
-com.sun.jersey:jersey-server:1.19.4
-com.sun.jersey:jersey-servlet:1.19.4
 com.sun.xml.bind:jaxb-impl:2.2.3-1
 javax.annotation:javax.annotation-api:1.3.2
 javax.cache:cache-api:1.1.1
@@ -513,6 +517,10 @@ javax.websocket:javax.websocket-api:1.0
 javax.ws.rs:jsr311-api:1.1.1
 javax.xml.bind:jaxb-api:2.2.11
 
+Eclipse Distribution License (EDL) 1.0
+--------------------------
+
+jakarta.xml.bind:jakarta.xml.bind-api:2.3.3
 
 Eclipse Public License 1.0
 --------------------------
@@ -520,6 +528,12 @@ Eclipse Public License 1.0
 junit:junit:4.13.2
 org.jacoco:org.jacoco.agent:0.8.5
 
+Eclipse Public License (EPL) 2.0
+--------------------------
+
+jakarta.ws.rs-api:jakarta.ws.rs-api:2.1.6
+jakarta.servlet.jsp:jakarta.servlet.jsp-api:2.3.6
+jakarta.servlet:jakarta.servlet-api:4.0.4
 
 
 HSQL License

+ 2 - 0
hadoop-client-modules/hadoop-client-check-invariants/pom.xml

@@ -88,6 +88,8 @@
                     <exclude>ch.qos.reload4j:reload4j</exclude>
                     <!-- Leave javax annotations we need exposed -->
                     <exclude>com.google.code.findbugs:jsr305</exclude>
+                    <exclude>jakarta.annotation:jakarta.annotation-api</exclude>
+                    <exclude>org.glassfish.jersey:*</exclude>
                     <!-- Leave bouncycastle unshaded because it's signed with a special Oracle certificate so it can be a custom JCE security provider -->
                     <exclude>org.bouncycastle:*</exclude>
                     <!-- Leave snappy that includes native methods which cannot be relocated. -->

+ 5 - 1
hadoop-client-modules/hadoop-client-check-invariants/src/test/resources/ensure-jars-have-correct-contents.sh

@@ -71,7 +71,11 @@ allowed_expr+="|^krb5_udp-template.conf$"
 allowed_expr+="|^jetty-dir.css$"
 # Snappy java is native library. We cannot relocate it to under org/apache/hadoop.
 allowed_expr+="|^org/xerial/"
-
+# Comes from jersey, not sure if relocatable.
+allowed_expr+="|^jersey"
+# Comes from jakarta, not sure if relocatable.
+allowed_expr+="|^javax"
+allowed_expr+="|^javassist"
 allowed_expr+=")"
 declare -i bad_artifacts=0
 declare -a bad_contents

+ 1 - 0
hadoop-client-modules/hadoop-client-check-test-invariants/pom.xml

@@ -101,6 +101,7 @@
                     <!-- Leave snappy that includes native methods which cannot be relocated. -->
                     <exclude>org.xerial.snappy:*</exclude>
                     <exclude>org.ehcache:*</exclude>
+                    <exclude>org.glassfish.jersey:*</exclude>
                   </excludes>
                 </banTransitiveDependencies>
                 <banDuplicateClasses>

+ 2 - 8
hadoop-client-modules/hadoop-client-integration-tests/pom.xml

@@ -86,14 +86,8 @@
           <scope>test</scope>
         </dependency>
         <dependency>
-          <groupId>javax.xml.bind</groupId>
-          <artifactId>jaxb-api</artifactId>
-          <scope>test</scope>
-        </dependency>
-        <dependency>
-          <groupId>javax.activation</groupId>
-          <artifactId>activation</artifactId>
-          <version>1.1.1</version>
+          <groupId>jakarta.xml.bind</groupId>
+          <artifactId>jakarta.xml.bind-api</artifactId>
           <scope>test</scope>
         </dependency>
       </dependencies>

+ 19 - 87
hadoop-client-modules/hadoop-client-minicluster/pom.xml

@@ -344,6 +344,10 @@
           <groupId>org.ow2.asm</groupId>
           <artifactId>asm-commons</artifactId>
         </exclusion>
+        <exclusion>
+          <groupId>org.ow2.asm</groupId>
+          <artifactId>asm-commons</artifactId>
+        </exclusion>
       </exclusions>
     </dependency>
     <!-- Add optional runtime dependency on the in-development timeline server module
@@ -415,72 +419,20 @@
     <!-- Skip commons-logging:commons-logging-api because it looks like nothing actually included it -->
     <!-- Skip jetty-util because it's in client -->
     <dependency>
-      <groupId>com.sun.jersey</groupId>
-      <artifactId>jersey-core</artifactId>
+      <groupId>org.glassfish.jersey.core</groupId>
+      <artifactId>jersey-common</artifactId>
       <optional>true</optional>
-      <exclusions>
-        <exclusion>
-          <groupId>javax.ws.rs</groupId>
-          <artifactId>jsr311-api</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-client</artifactId>
+       <groupId>org.glassfish.jersey.core</groupId>
+       <artifactId>jersey-client</artifactId>
       <optional>true</optional>
     </dependency>
     <dependency>
-      <groupId>com.github.pjfanning</groupId>
-      <artifactId>jersey-json</artifactId>
-      <optional>true</optional>
-      <exclusions>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>jackson-core</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>jackson-databind</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.jaxrs</groupId>
-          <artifactId>jackson-jaxrs-json-provider</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>javax.xml.bind</groupId>
-          <artifactId>jaxb-api</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.codehaus.jettison</groupId>
-          <artifactId>jettison</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>com.sun.jersey</groupId>
+      <groupId>org.glassfish.jersey.core</groupId>
       <artifactId>jersey-server</artifactId>
       <optional>true</optional>
     </dependency>
-    <dependency>
-      <groupId>com.sun.jersey</groupId>
-      <artifactId>jersey-servlet</artifactId>
-      <optional>true</optional>
-      <exclusions>
-        <exclusion>
-          <groupId>javax.servlet</groupId>
-          <artifactId>servlet-api</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>javax.enterprise</groupId>
-          <artifactId>cdi-api</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>ch.qos.cal10n</groupId>
-          <artifactId>cal10n-api</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <!-- skip org.apache.avro:avro-ipc because it doesn't look like hadoop-common actually uses it -->
     <dependency>
       <groupId>net.sf.kosmosfs</groupId>
@@ -624,23 +576,16 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey.jersey-test-framework</groupId>
-      <artifactId>jersey-test-framework-grizzly2</artifactId>
+      <groupId>org.glassfish.jersey.test-framework</groupId>
+      <artifactId>jersey-test-framework-core</artifactId>
       <optional>true</optional>
-      <exclusions>
-        <!-- excluding because client already has the tomcat version -->
-        <exclusion>
-          <groupId>org.glassfish</groupId>
-          <artifactId>javax.servlet</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
-    <!-- skipping jersey-server because it's above -->
     <dependency>
-      <groupId>com.sun.jersey.contribs</groupId>
-      <artifactId>jersey-guice</artifactId>
+      <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+      <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
       <optional>true</optional>
     </dependency>
+    <!-- skipping jersey-server because it's above -->
     <!-- skipping guice-servlet because it's above -->
     <!-- skipping avro because it is in client via hadoop-common -->
     <!-- skipping jersey-core because it's above -->
@@ -709,6 +654,10 @@
                       <exclude>org.bouncycastle:*</exclude>
                       <!-- Leave snappy that includes native methods which cannot be relocated. -->
                       <exclude>org.xerial.snappy:*</exclude>
+                      <exclude>org.glassfish.jersey:*</exclude>
+                      <exclude>org.hamcrest:*</exclude>
+                      <exclude>aopalliance:*</exclude>
+                      <exclude>javassist:*</exclude>
                     </excludes>
                   </artifactSet>
                   <filters>
@@ -729,24 +678,6 @@
                     <!-- Since runtime has classes for these jars, we exclude them.
                          We still want the java services api files, since those were excluded in runtime
                       -->
-                    <filter>
-                      <artifact>com.sun.jersey:jersey-client</artifact>
-                      <excludes>
-                        <exclude>**/*.class</exclude>
-                      </excludes>
-                    </filter>
-                    <filter>
-                      <artifact>com.sun.jersey:jersey-core</artifact>
-                      <excludes>
-                        <exclude>**/*.class</exclude>
-                      </excludes>
-                    </filter>
-                    <filter>
-                      <artifact>com.sun.jersey:jersey-servlet</artifact>
-                      <excludes>
-                        <exclude>**/*.class</exclude>
-                      </excludes>
-                    </filter>
                     <filter>
                       <artifact>org.apache.hadoop:hadoop-mapreduce-client-jobclient:*</artifact>
                       <excludes>
@@ -760,6 +691,7 @@
                       <excludes>
                         <exclude>META-INF/versions/9/module-info.class</exclude>
                         <exclude>META-INF/versions/11/module-info.class</exclude>
+                        <exclude>META-INF/versions/9/javax/xml/bind/ModuleUtil.class</exclude>
                       </excludes>
                     </filter>
 

+ 19 - 7
hadoop-client-modules/hadoop-client-runtime/pom.xml

@@ -159,6 +159,24 @@
                       <exclude>org.xerial.snappy:*</exclude>
                       <!-- leave out kotlin classes -->
                       <exclude>org.jetbrains.kotlin:*</exclude>
+                      <exclude>org.glassfish.jersey.test-framework:*</exclude>
+                      <exclude>org.glassfish.jersey.media:*</exclude>
+                      <exclude>org.glassfish.jersey.containers:*</exclude>
+                      <exclude>org.glassfish.jersey.test-framework.providers:*</exclude>
+                      <exclude>org.glassfish.hk2:*</exclude>
+                      <exclude>org.glassfish.jersey.inject:*</exclude>
+                      <exclude>org.glassfish.grizzly:*</exclude>
+                      <exclude>org.glassfish.jersey.core:*</exclude>
+                      <exclude>org.glassfish.hk2.external:*</exclude>
+                      <exclude>org.glassfish.jaxb:*</exclude>
+                      <exclude>jakarta.ws.rs:*</exclude>
+                      <exclude>jakarta.annotation:*</exclude>
+                      <exclude>jakarta.validation:*</exclude>
+                      <exclude>jakarta.servlet:*</exclude>
+                      <exclude>javax.annotation:*</exclude>
+                      <exclude>org.hamcrest:*</exclude>
+                      <exclude>aopalliance:*</exclude>
+                      <exclude>javassist:*</exclude>
                     </excludes>
                   </artifactSet>
                   <filters>
@@ -184,13 +202,6 @@
                         <exclude>org/apache/jasper/compiler/Localizer.class</exclude>
                       </excludes>
                     </filter>
-                    <!-- We rely on jersey for our web interfaces. We want to use its java services stuff only internal to jersey -->
-                    <filter>
-                      <artifact>com.sun.jersey:*</artifact>
-                      <excludes>
-                        <exclude>META-INF/services/javax.*</exclude>
-                      </excludes>
-                    </filter>
                     <filter>
                       <!-- skip french localization -->
                       <artifact>org.apache.commons:commons-math3</artifact>
@@ -247,6 +258,7 @@
                         <exclude>META-INF/versions/9/module-info.class</exclude>
                         <exclude>META-INF/versions/11/module-info.class</exclude>
                         <exclude>META-INF/versions/18/module-info.class</exclude>
+                        <exclude>META-INF/versions/9/javax/xml/bind/ModuleUtil.class</exclude>
                       </excludes>
                     </filter>
 

+ 0 - 76
hadoop-client-modules/hadoop-client/pom.xml

@@ -61,22 +61,10 @@
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>servlet-api-2.5</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-core</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.github.pjfanning</groupId>
-          <artifactId>jersey-json</artifactId>
-        </exclusion>
         <exclusion>
           <groupId>org.codehaus.jettison</groupId>
           <artifactId>jettison</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-server</artifactId>
-        </exclusion>
         <exclusion>
           <groupId>org.eclipse.jdt</groupId>
           <artifactId>core</artifactId>
@@ -118,18 +106,6 @@
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-server</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-core</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-server</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>javax.servlet</groupId>
-          <artifactId>javax.servlet-api</artifactId>
-        </exclusion>
       </exclusions>
     </dependency>
 
@@ -146,18 +122,6 @@
           <groupId>com.google.inject</groupId>
           <artifactId>guice</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey.jersey-test-framework</groupId>
-          <artifactId>jersey-test-framework-grizzly2</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-server</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey.contribs</groupId>
-          <artifactId>jersey-guice</artifactId>
-        </exclusion>
         <exclusion>
           <groupId>com.google.inject.extensions</groupId>
           <artifactId>guice-servlet</artifactId>
@@ -166,14 +130,6 @@
           <groupId>org.apache.avro</groupId>
           <artifactId>avro</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-core</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.github.pjfanning</groupId>
-          <artifactId>jersey-json</artifactId>
-        </exclusion>
         <exclusion>
           <groupId>org.codehaus.jettison</groupId>
           <artifactId>jettison</artifactId>
@@ -217,26 +173,10 @@
           <groupId>ch.qos.reload4j</groupId>
           <artifactId>reload4j</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-core</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-server</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.github.pjfanning</groupId>
-          <artifactId>jersey-json</artifactId>
-        </exclusion>
         <exclusion>
           <groupId>org.codehaus.jettison</groupId>
           <artifactId>jettison</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-servlet</artifactId>
-        </exclusion>
         <exclusion>
           <groupId>io.netty</groupId>
           <artifactId>netty</artifactId>
@@ -262,18 +202,6 @@
           <groupId>com.google.inject</groupId>
           <artifactId>guice</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey.jersey-test-framework</groupId>
-          <artifactId>jersey-test-framework-grizzly2</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-server</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey.contribs</groupId>
-          <artifactId>jersey-guice</artifactId>
-        </exclusion>
         <exclusion>
           <groupId>org.apache.avro</groupId>
           <artifactId>avro</artifactId>
@@ -286,10 +214,6 @@
           <groupId>com.google.inject.extensions</groupId>
           <artifactId>guice-servlet</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.github.pjfanning</groupId>
-          <artifactId>jersey-json</artifactId>
-        </exclusion>
         <exclusion>
           <groupId>org.codehaus.jettison</groupId>
           <artifactId>jettison</artifactId>

+ 0 - 12
hadoop-cloud-storage-project/hadoop-cloud-storage/pom.xml

@@ -69,18 +69,6 @@
           <groupId>org.mortbay.jetty</groupId>
           <artifactId>servlet-api-2.5</artifactId>
         </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-core</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-json</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-server</artifactId>
-        </exclusion>
         <exclusion>
           <groupId>org.eclipse.jdt</groupId>
           <artifactId>core</artifactId>

+ 6 - 0
hadoop-cloud-storage-project/hadoop-huaweicloud/pom.xml

@@ -137,6 +137,12 @@
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-yarn-server-tests</artifactId>
       <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>javassist</artifactId>
+          <groupId>org.javassist</groupId>
+        </exclusion>
+      </exclusions>
       <type>test-jar</type>
     </dependency>
     <dependency>

+ 1 - 1
hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSBlockOutputStream.java

@@ -31,7 +31,6 @@ import com.obs.services.model.PutObjectRequest;
 import com.obs.services.model.UploadPartRequest;
 import com.obs.services.model.UploadPartResult;
 import com.obs.services.model.fs.WriteFileRequest;
-import com.sun.istack.NotNull;
 
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
@@ -39,6 +38,7 @@ import org.apache.hadoop.fs.Syncable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.validation.constraints.NotNull;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;

+ 1 - 1
hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSInputStream.java

@@ -22,7 +22,6 @@ import org.apache.hadoop.util.Preconditions;
 import com.obs.services.ObsClient;
 import com.obs.services.exception.ObsException;
 import com.obs.services.model.GetObjectRequest;
-import com.sun.istack.NotNull;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.classification.InterfaceAudience;
@@ -35,6 +34,7 @@ import org.apache.hadoop.fs.FileSystem;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.validation.constraints.NotNull;
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;

+ 2 - 2
hadoop-common-project/hadoop-auth-examples/pom.xml

@@ -32,8 +32,8 @@
 
   <dependencies>
     <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
+      <groupId>jakarta.servlet</groupId>
+      <artifactId>jakarta.servlet-api</artifactId>
       <scope>provided</scope>
     </dependency>
     <dependency>

+ 2 - 2
hadoop-common-project/hadoop-auth/pom.xml

@@ -68,8 +68,8 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
+      <groupId>jakarta.servlet</groupId>
+      <artifactId>jakarta.servlet-api</artifactId>
       <scope>provided</scope>
     </dependency>
     <dependency>

+ 31 - 66
hadoop-common-project/hadoop-common/pom.xml

@@ -93,104 +93,69 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
+      <groupId>jakarta.servlet.jsp</groupId>
+      <artifactId>jakarta.servlet.jsp-api</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>jakarta.activation</groupId>
-      <artifactId>jakarta.activation-api</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-server</artifactId>
+      <groupId>jakarta.ws.rs</groupId>
+      <artifactId>jakarta.ws.rs-api</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-util</artifactId>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <groupId>org.glassfish.jersey.core</groupId>
+      <artifactId>jersey-server</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-webapp</artifactId>
-      <scope>compile</scope>
+      <groupId>org.glassfish.jersey.containers</groupId>
+      <artifactId>jersey-container-servlet</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>javax.servlet</groupId>
+          <artifactId>javax.servlet-api</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-util-ajax</artifactId>
-      <scope>test</scope>
+      <groupId>org.glassfish.jersey.inject</groupId>
+      <artifactId>jersey-hk2</artifactId>
     </dependency>
     <dependency>
-      <groupId>javax.servlet.jsp</groupId>
-      <artifactId>jsp-api</artifactId>
+      <groupId>jakarta.activation</groupId>
+      <artifactId>jakarta.activation-api</artifactId>
       <scope>runtime</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
-      <artifactId>jersey-core</artifactId>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
-      <artifactId>jersey-servlet</artifactId>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-util</artifactId>
       <scope>compile</scope>
       <exclusions>
         <exclusion>
-          <groupId>javax.enterprise</groupId>
-          <artifactId>cdi-api</artifactId>
-        </exclusion>
-        <exclusion>
+          <artifactId>javax.servlet-api</artifactId>
           <groupId>javax.servlet</groupId>
-          <artifactId>servlet-api</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>ch.qos.cal10n</groupId>
-          <artifactId>cal10n-api</artifactId>
         </exclusion>
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>com.github.pjfanning</groupId>
-      <artifactId>jersey-json</artifactId>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-servlet</artifactId>
       <scope>compile</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>jackson-core</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>jackson-databind</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.jaxrs</groupId>
-          <artifactId>jackson-jaxrs-json-provider</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.codehaus.jettison</groupId>
-          <artifactId>jettison</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
-      <!--
-      adding jettison as direct dependency (as jersey-json's jettison dependency is vulnerable with verison 1.1),
-      so those who depends on hadoop-common externally will get the non-vulnerable jettison
-      -->
-      <groupId>org.codehaus.jettison</groupId>
-      <artifactId>jettison</artifactId>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-webapp</artifactId>
+      <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
-      <artifactId>jersey-server</artifactId>
-      <scope>compile</scope>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-util-ajax</artifactId>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>ch.qos.reload4j</groupId>

+ 25 - 9
hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java

@@ -59,7 +59,8 @@ import org.apache.hadoop.classification.VisibleForTesting;
 import org.apache.hadoop.jmx.JMXJsonServletNaNFiltered;
 import org.apache.hadoop.util.Preconditions;
 import org.apache.hadoop.thirdparty.com.google.common.collect.ImmutableMap;
-import com.sun.jersey.spi.container.servlet.ServletContainer;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.servlet.ServletContainer;
 import org.apache.hadoop.HadoopIllegalArgumentException;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
@@ -1017,8 +1018,7 @@ public final class HttpServer2 implements FilterContainer {
    */
   public void addJerseyResourcePackage(final String packageName,
       final String pathSpec) {
-    addJerseyResourcePackage(packageName, pathSpec,
-        Collections.<String, String>emptyMap());
+    addJerseyResourcePackage(packageName, pathSpec, Collections.emptyMap());
   }
 
   /**
@@ -1029,18 +1029,34 @@ public final class HttpServer2 implements FilterContainer {
    */
   public void addJerseyResourcePackage(final String packageName,
       final String pathSpec, Map<String, String> params) {
-    LOG.info("addJerseyResourcePackage: packageName=" + packageName
-        + ", pathSpec=" + pathSpec);
-    final ServletHolder sh = new ServletHolder(ServletContainer.class);
-    sh.setInitParameter("com.sun.jersey.config.property.resourceConfigClass",
-        "com.sun.jersey.api.core.PackagesResourceConfig");
-    sh.setInitParameter("com.sun.jersey.config.property.packages", packageName);
+    LOG.info("addJerseyResourcePackage: packageName = {}, pathSpec = {}.",
+        packageName, pathSpec);
+    final ResourceConfig config = new ResourceConfig().packages(packageName);
+    final ServletHolder sh = new ServletHolder(new ServletContainer(config));
     for (Map.Entry<String, String> entry : params.entrySet()) {
       sh.setInitParameter(entry.getKey(), entry.getValue());
     }
     webAppContext.addServlet(sh, pathSpec);
   }
 
+  /**
+   * Add a Jersey resource config.
+   * @param config The Jersey ResourceConfig to be registered.
+   * @param pathSpec The path spec for the servlet
+   * @param params properties and features for ResourceConfig
+   */
+  public void addJerseyResourceConfig(final ResourceConfig config,
+      final String pathSpec, Map<String, String> params) {
+    LOG.info("addJerseyResourceConfig: pathSpec = {}.", pathSpec);
+    final ServletHolder sh = new ServletHolder(new ServletContainer(config));
+    if (params != null) {
+      for (Map.Entry<String, String> entry : params.entrySet()) {
+        sh.setInitParameter(entry.getKey(), entry.getValue());
+      }
+    }
+    webAppContext.addServlet(sh, pathSpec);
+  }
+
   /**
    * Add a servlet in the server.
    * @param name The name of the servlet (can be passed as null)

+ 9 - 9
hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java

@@ -82,7 +82,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
   public static class EchoMapServlet extends HttpServlet {
     @SuppressWarnings("unchecked")
     @Override
-    public void doGet(HttpServletRequest request, 
+    public void doGet(HttpServletRequest request,
                       HttpServletResponse response
                       ) throws ServletException, IOException {
       response.setContentType(MediaType.TEXT_PLAIN + "; " + JettyUtils.UTF_8);
@@ -110,7 +110,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
   public static class EchoServlet extends HttpServlet {
     @SuppressWarnings("unchecked")
     @Override
-    public void doGet(HttpServletRequest request, 
+    public void doGet(HttpServletRequest request,
                       HttpServletResponse response
                       ) throws ServletException, IOException {
       response.setContentType(MediaType.TEXT_PLAIN + "; " + JettyUtils.UTF_8);
@@ -133,7 +133,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
   @SuppressWarnings("serial")
   public static class HtmlContentServlet extends HttpServlet {
     @Override
-    public void doGet(HttpServletRequest request, 
+    public void doGet(HttpServletRequest request,
                       HttpServletResponse response
                       ) throws ServletException, IOException {
       response.setContentType(MediaType.TEXT_HTML + "; " + JettyUtils.UTF_8);
@@ -417,10 +417,10 @@ public class TestHttpServer extends HttpServerFunctionalTest {
    * will be accessed as the passed user, by sending user.name request
    * parameter.
    * 
-   * @param urlstring
-   * @param userName
-   * @return
-   * @throws IOException
+   * @param urlstring web url.
+   * @param userName userName.
+   * @return http status code.
+   * @throws IOException an I/O exception of some sort has occurred.
    */
   static int getHttpStatusCode(String urlstring, String userName)
       throws IOException {
@@ -458,7 +458,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
    * Verify the access for /logs, /stacks, /conf, and /logLevel
    * servlets, when authentication filters are set, but authorization is not
    * enabled.
-   * @throws Exception 
+   * @throws Exception if there is an error during, an exception will be thrown.
    */
   @Test
   public void testDisabledAuthorizationOfDefaultServlets() throws Exception {
@@ -494,7 +494,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
    * Verify the administrator access for /logs, /stacks, /conf, and /logLevel
    * servlets.
    * 
-   * @throws Exception
+   * @throws Exception if there is an error during, an exception will be thrown.
    */
   @Test
   public void testAuthorizationOfDefaultServlets() throws Exception {

+ 4 - 5
hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerLogs.java

@@ -20,7 +20,6 @@ package org.apache.hadoop.http;
 import org.apache.http.HttpStatus;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
-import org.apache.hadoop.http.resource.JerseyResource;
 import org.apache.hadoop.net.NetUtils;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -29,7 +28,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
 import java.net.URL;
+import java.util.Objects;
 
 public class TestHttpServerLogs extends HttpServerFunctionalTest {
   static final Logger LOG = LoggerFactory.getLogger(TestHttpServerLogs.class);
@@ -41,8 +42,6 @@ public class TestHttpServerLogs extends HttpServerFunctionalTest {
 
   private void startServer(Configuration conf) throws Exception {
     server = createTestServer(conf);
-    server.addJerseyResourcePackage(
-        JerseyResource.class.getPackage().getName(), "/jersey/*");
     server.start();
     baseUrl = getServerURL(server);
     LOG.info("HTTP server started: "+ baseUrl);
@@ -61,8 +60,8 @@ public class TestHttpServerLogs extends HttpServerFunctionalTest {
     conf.setBoolean(
         CommonConfigurationKeysPublic.HADOOP_HTTP_LOGS_ENABLED, true);
     startServer(conf);
-    URL url = new URL("http://"
-        + NetUtils.getHostPortString(server.getConnectorAddress(0)) + "/logs");
+    InetSocketAddress inetSocketAddress = Objects.requireNonNull(server.getConnectorAddress(0));
+    URL url = new URL("http://" + NetUtils.getHostPortString(inetSocketAddress) + "/logs");
     HttpURLConnection conn = (HttpURLConnection)url.openConnection();
     assertEquals(HttpStatus.SC_OK, conn.getResponseCode());
   }

+ 10 - 5
hadoop-common-project/hadoop-kms/pom.xml

@@ -59,18 +59,23 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
-      <artifactId>jersey-core</artifactId>
+      <groupId>org.glassfish.jersey.core</groupId>
+      <artifactId>jersey-common</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
+      <groupId>org.glassfish.jersey.core</groupId>
       <artifactId>jersey-server</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
+      <groupId>org.glassfish.jersey.inject</groupId>
+      <artifactId>jersey-hk2</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>jakarta.servlet</groupId>
+      <artifactId>jakarta.servlet-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jetty</groupId>

+ 0 - 1
hadoop-common-project/hadoop-kms/src/main/conf/kms-log4j.properties

@@ -34,7 +34,6 @@ log4j.additivity.kms-audit=false
 
 log4j.rootLogger=INFO, kms
 log4j.logger.org.apache.hadoop=INFO
-log4j.logger.com.sun.jersey.server.wadl.generators.WadlGeneratorJAXBGrammarGenerator=OFF
 # make zookeeper log level an explicit config, and not changing with rootLogger.
 log4j.logger.org.apache.zookeeper=INFO
 log4j.logger.org.apache.curator=INFO

+ 10 - 4
hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java

@@ -39,6 +39,7 @@ import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
@@ -114,6 +115,14 @@ public class KMS {
         .build(domain, KMSRESTConstants.KEY_RESOURCE, keyName);
   }
 
+  @OPTIONS
+  public Response handleOptions() {
+    return Response.ok()
+        .header("Allow", "GET")
+        .header("Allow", "OPTIONS")
+        .build();
+  }
+
   @POST
   @Path(KMSRESTConstants.KEYS_RESOURCE)
   @Consumes(MediaType.APPLICATION_JSON)
@@ -175,13 +184,10 @@ public class KMS {
         keyVersion = removeKeyMaterial(keyVersion);
       }
       Map json = KMSUtil.toJSON(keyVersion);
-      String requestURL = KMSMDCFilter.getURL();
-      int idx = requestURL.lastIndexOf(KMSRESTConstants.KEYS_RESOURCE);
-      requestURL = requestURL.substring(0, idx);
       LOG.trace("Exiting createKey Method.");
       return Response.created(getKeyURI(KMSRESTConstants.SERVICE_VERSION, name))
           .type(MediaType.APPLICATION_JSON)
-          .header("Location", getKeyURI(requestURL, name)).entity(json).build();
+          .entity(json).build();
     } catch (Exception e) {
       LOG.debug("Exception in createKey.", e);
       throw e;

+ 1 - 1
hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSExceptionsProvider.java

@@ -19,7 +19,7 @@ package org.apache.hadoop.crypto.key.kms.server;
 
 import org.apache.hadoop.classification.InterfaceAudience;
 
-import com.sun.jersey.api.container.ContainerException;
+import org.glassfish.jersey.server.ContainerException;
 
 import org.apache.hadoop.security.AccessControlException;
 import org.apache.hadoop.security.UserGroupInformation;

+ 2 - 14
hadoop-common-project/hadoop-kms/src/main/resources/webapps/kms/WEB-INF/web.xml

@@ -20,23 +20,11 @@
 
   <servlet>
     <servlet-name>webservices-driver</servlet-name>
-    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
     <init-param>
-      <param-name>com.sun.jersey.config.property.packages</param-name>
+      <param-name>jersey.config.server.provider.packages</param-name>
       <param-value>org.apache.hadoop.crypto.key.kms.server</param-value>
     </init-param>
-
-    <!-- Enables detailed Jersey request/response logging -->
-    <!--
-    <init-param>
-        <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
-        <param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
-    </init-param>
-    <init-param>
-        <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
-        <param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
-    </init-param>
-    -->
     <load-on-startup>1</load-on-startup>
   </servlet>
 

+ 2 - 2
hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java

@@ -583,9 +583,9 @@ public class TestKMS {
   @Test
   public void testStartStopHttpPseudo() throws Exception {
     // Make sure bogus errors don't get emitted.
+    // Jersey2 does not have a method similar to AbstractWadlGeneratorGrammarGenerator.
     GenericTestUtils.LogCapturer logs =
-        GenericTestUtils.LogCapturer.captureLogs(LoggerFactory.getLogger(
-            "com.sun.jersey.server.wadl.generators.AbstractWadlGeneratorGrammarGenerator"));
+        GenericTestUtils.LogCapturer.captureLogs(LOG);
     try {
       testStartStop(false, false);
     } finally {

+ 0 - 2
hadoop-common-project/hadoop-kms/src/test/resources/log4j.properties

@@ -25,8 +25,6 @@ log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{1} - %m%n
 log4j.rootLogger=INFO, stdout
 log4j.logger.org.apache.hadoop.conf=ERROR
 log4j.logger.org.apache.hadoop.crytpo.key.kms.server=ALL
-log4j.logger.com.sun.jersey.server.wadl.generators.WadlGeneratorJAXBGrammarGenerator=OFF
-log4j.logger.com.sun.jersey.server.wadl.generators.AbstractWadlGeneratorGrammarGenerator=OFF
 log4j.logger.org.apache.hadoop.security=OFF
 log4j.logger.org.apache.directory.server.core=OFF
 log4j.logger.org.apache.hadoop.util.NativeCodeLoader=OFF

+ 2 - 2
hadoop-common-project/hadoop-nfs/pom.xml

@@ -64,8 +64,8 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
+      <groupId>jakarta.servlet</groupId>
+      <artifactId>jakarta.servlet-api</artifactId>
       <scope>provided</scope>
     </dependency>
     <dependency>

+ 5 - 0
hadoop-hdfs-project/hadoop-hdfs-client/pom.xml

@@ -59,6 +59,11 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <artifactId>httpcore</artifactId>
       <version>${httpcore.version}</version>
     </dependency>
+    <dependency>
+      <groupId>jakarta.ws.rs</groupId>
+      <artifactId>jakarta.ws.rs-api</artifactId>
+      <scope>compile</scope>
+    </dependency>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>

+ 6 - 5
hadoop-hdfs-project/hadoop-hdfs-httpfs/pom.xml

@@ -58,18 +58,19 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
-      <artifactId>jersey-core</artifactId>
+      <groupId>org.glassfish.jersey.core</groupId>
+      <artifactId>jersey-common</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
+      <groupId>org.glassfish.jersey.core</groupId>
       <artifactId>jersey-server</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
+      <groupId>jakarta.servlet</groupId>
+      <artifactId>jakarta.servlet-api</artifactId>
+      <scope>compile</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop.thirdparty</groupId>

+ 1 - 1
hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/server/HttpFSExceptionProvider.java

@@ -18,7 +18,7 @@
 
 package org.apache.hadoop.fs.http.server;
 
-import com.sun.jersey.api.container.ContainerException;
+import org.glassfish.jersey.server.ContainerException;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.lib.service.FileSystemAccessException;
 import org.apache.hadoop.lib.wsrs.ExceptionProvider;

+ 0 - 2
hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/server/HttpFSParametersProvider.java

@@ -34,7 +34,6 @@ import org.apache.hadoop.lib.wsrs.ParametersProvider;
 import org.apache.hadoop.lib.wsrs.ShortParam;
 import org.apache.hadoop.lib.wsrs.StringParam;
 import org.apache.hadoop.util.StringUtils;
-import javax.ws.rs.ext.Provider;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.regex.Pattern;
@@ -42,7 +41,6 @@ import java.util.regex.Pattern;
 /**
  * HttpFS ParametersProvider.
  */
-@Provider
 @InterfaceAudience.Private
 @SuppressWarnings("unchecked")
 public class HttpFSParametersProvider extends ParametersProvider {

+ 24 - 21
hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/server/HttpFSServer.java

@@ -140,6 +140,14 @@ public class HttpFSServer {
     return UserGroupInformation.createRemoteUser(request.getUserPrincipal().getName());
   }
 
+  private static final HttpFSParametersProvider PARAMETERS_PROVIDER =
+      new HttpFSParametersProvider();
+
+  private Parameters getParams(HttpServletRequest request) {
+    return PARAMETERS_PROVIDER.get(request);
+  }
+
+  private static final Object[] NULL = new Object[0];
 
   /**
    * Executes a {@link FileSystemAccess.FileSystemExecutor} using a filesystem for the effective
@@ -200,7 +208,6 @@ public class HttpFSServer {
    *
    * @param uriInfo uri info of the request.
    * @param op the HttpFS operation of the request.
-   * @param params the HttpFS parameters of the request.
    *
    * @return the request response.
    *
@@ -214,10 +221,9 @@ public class HttpFSServer {
   @Produces(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8)
   public Response getRoot(@Context UriInfo uriInfo,
                           @QueryParam(OperationParam.NAME) OperationParam op,
-                          @Context Parameters params,
                           @Context HttpServletRequest request)
     throws IOException, FileSystemAccessException {
-    return get("", uriInfo, op, params, request);
+    return get("", uriInfo, op, request);
   }
 
   private String makeAbsolute(String path) {
@@ -230,7 +236,6 @@ public class HttpFSServer {
    * @param path the path for operation.
    * @param uriInfo uri info of the request.
    * @param op the HttpFS operation of the request.
-   * @param params the HttpFS parameters of the request.
    *
    * @return the request response.
    *
@@ -247,7 +252,6 @@ public class HttpFSServer {
   public Response get(@PathParam("path") String path,
                       @Context UriInfo uriInfo,
                       @QueryParam(OperationParam.NAME) OperationParam op,
-                      @Context Parameters params,
                       @Context HttpServletRequest request)
     throws IOException, FileSystemAccessException {
     // Restrict access to only GETFILESTATUS and LISTSTATUS in write-only mode
@@ -259,6 +263,7 @@ public class HttpFSServer {
     UserGroupInformation user = HttpUserGroupInformation.get();
     Response response;
     path = makeAbsolute(path);
+    final Parameters params = getParams(request);
     MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name());
     MDC.put("hostname", request.getRemoteAddr());
     switch (op.value()) {
@@ -610,7 +615,6 @@ public class HttpFSServer {
    *
    * @param path the path for operation.
    * @param op the HttpFS operation of the request.
-   * @param params the HttpFS parameters of the request.
    *
    * @return the request response.
    *
@@ -625,7 +629,6 @@ public class HttpFSServer {
   @Produces(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8)
   public Response delete(@PathParam("path") String path,
                          @QueryParam(OperationParam.NAME) OperationParam op,
-                         @Context Parameters params,
                          @Context HttpServletRequest request)
     throws IOException, FileSystemAccessException {
     // Do not allow DELETE commands in read-only mode
@@ -635,6 +638,7 @@ public class HttpFSServer {
     UserGroupInformation user = HttpUserGroupInformation.get();
     Response response;
     path = makeAbsolute(path);
+    final Parameters params = getParams(request);
     MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name());
     MDC.put("hostname", request.getRemoteAddr());
     switch (op.value()) {
@@ -672,7 +676,7 @@ public class HttpFSServer {
    * @param is the inputstream for the request payload.
    * @param uriInfo the of the request.
    * @param op the HttpFS operation of the request.
-   * @param params the HttpFS parameters of the request.
+   * @param request the HttpFS request.
    *
    * @return the request response.
    *
@@ -686,9 +690,9 @@ public class HttpFSServer {
   @Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8 })
   public Response postRoot(InputStream is, @Context UriInfo uriInfo,
       @QueryParam(OperationParam.NAME) OperationParam op,
-      @Context Parameters params, @Context HttpServletRequest request)
+      @Context HttpServletRequest request)
       throws IOException, FileSystemAccessException {
-    return post(is, uriInfo, "/", op, params, request);
+    return post(is, uriInfo, "/", op, request);
   }
 
   /**
@@ -698,7 +702,6 @@ public class HttpFSServer {
    * @param uriInfo the of the request.
    * @param path the path for operation.
    * @param op the HttpFS operation of the request.
-   * @param params the HttpFS parameters of the request.
    *
    * @return the request response.
    *
@@ -716,7 +719,6 @@ public class HttpFSServer {
                        @Context UriInfo uriInfo,
                        @PathParam("path") String path,
                        @QueryParam(OperationParam.NAME) OperationParam op,
-                       @Context Parameters params,
                        @Context HttpServletRequest request)
     throws IOException, FileSystemAccessException {
     // Do not allow POST commands in read-only mode
@@ -726,6 +728,7 @@ public class HttpFSServer {
     UserGroupInformation user = HttpUserGroupInformation.get();
     Response response;
     path = makeAbsolute(path);
+    final Parameters params = getParams(request);
     MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name());
     MDC.put("hostname", request.getRemoteAddr());
     switch (op.value()) {
@@ -802,10 +805,11 @@ public class HttpFSServer {
    */
   protected URI createUploadRedirectionURL(UriInfo uriInfo, Enum<?> uploadOperation) {
     UriBuilder uriBuilder = uriInfo.getRequestUriBuilder();
-    uriBuilder = uriBuilder.replaceQueryParam(OperationParam.NAME, uploadOperation).
-            queryParam(DataParam.NAME, Boolean.TRUE)
-            .replaceQueryParam(NoRedirectParam.NAME, (Object[]) null);
-    return uriBuilder.build(null);
+    uriBuilder = uriBuilder.replaceQueryParam(OperationParam.NAME, uploadOperation)
+        .queryParam(DataParam.NAME, Boolean.TRUE)
+        .replaceQueryParam(NoRedirectParam.NAME, (Object[]) null);
+    // Workaround: NPE occurs when using null in Jersey 2.29
+    return uriBuilder.build(NULL);
   }
 
   /**
@@ -813,7 +817,7 @@ public class HttpFSServer {
    * @param is the inputstream for the request payload.
    * @param uriInfo the of the request.
    * @param op the HttpFS operation of the request.
-   * @param params the HttpFS parameters of the request.
+   * @param request the HttpFS request.
    *
    * @return the request response.
    *
@@ -827,9 +831,9 @@ public class HttpFSServer {
   @Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8 })
   public Response putRoot(InputStream is, @Context UriInfo uriInfo,
       @QueryParam(OperationParam.NAME) OperationParam op,
-      @Context Parameters params, @Context HttpServletRequest request)
+      @Context HttpServletRequest request)
       throws IOException, FileSystemAccessException {
-    return put(is, uriInfo, "/", op, params, request);
+    return put(is, uriInfo, "/", op, request);
   }
 
   /**
@@ -839,7 +843,6 @@ public class HttpFSServer {
    * @param uriInfo the of the request.
    * @param path the path for operation.
    * @param op the HttpFS operation of the request.
-   * @param params the HttpFS parameters of the request.
    *
    * @return the request response.
    *
@@ -857,7 +860,6 @@ public class HttpFSServer {
                        @Context UriInfo uriInfo,
                        @PathParam("path") String path,
                        @QueryParam(OperationParam.NAME) OperationParam op,
-                       @Context Parameters params,
                        @Context HttpServletRequest request)
     throws IOException, FileSystemAccessException {
     // Do not allow PUT commands in read-only mode
@@ -867,6 +869,7 @@ public class HttpFSServer {
     UserGroupInformation user = HttpUserGroupInformation.get();
     Response response;
     path = makeAbsolute(path);
+    final Parameters params = getParams(request);
     MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name());
     MDC.put("hostname", request.getRemoteAddr());
     switch (op.value()) {

+ 4 - 10
hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/lib/wsrs/JSONMapProvider.java

@@ -30,8 +30,6 @@ import javax.ws.rs.ext.MessageBodyWriter;
 import javax.ws.rs.ext.Provider;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.nio.charset.StandardCharsets;
@@ -55,13 +53,9 @@ public class JSONMapProvider implements MessageBodyWriter<Map> {
 
   @Override
   public void writeTo(Map map, Class<?> aClass, Type type, Annotation[] annotations,
-                      MediaType mediaType, MultivaluedMap<String, Object> stringObjectMultivaluedMap,
-                      OutputStream outputStream) throws IOException, WebApplicationException {
-    Writer writer =
-        new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
-    JSONObject.writeJSONString(map, writer);
-    writer.write(ENTER);
-    writer.flush();
+      MediaType mediaType, MultivaluedMap<String, Object> stringObjectMultivaluedMap,
+      OutputStream outputStream) throws IOException, WebApplicationException {
+    String value = JSONObject.toJSONString(map) + ENTER;
+    outputStream.write(value.getBytes(StandardCharsets.UTF_8));
   }
-
 }

+ 23 - 44
hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/lib/wsrs/ParametersProvider.java

@@ -18,52 +18,52 @@
 
 package org.apache.hadoop.lib.wsrs;
 
-import com.sun.jersey.api.core.HttpContext;
-import com.sun.jersey.core.spi.component.ComponentContext;
-import com.sun.jersey.core.spi.component.ComponentScope;
-import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable;
-import com.sun.jersey.spi.inject.Injectable;
-import com.sun.jersey.spi.inject.InjectableProvider;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.util.Lists;
 import org.apache.hadoop.util.StringUtils;
 
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MultivaluedMap;
-import java.lang.reflect.Type;
+import javax.servlet.http.HttpServletRequest;
 import java.text.MessageFormat;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 /**
- * Jersey provider that parses the request parameters based on the
+ * Provider that parses the request parameters based on the
  * given parameter definition. 
  */
 @InterfaceAudience.Private
-public class ParametersProvider
-  extends AbstractHttpContextInjectable<Parameters>
-  implements InjectableProvider<Context, Type> {
+public class ParametersProvider {
 
   private String driverParam;
   private Class<? extends Enum> enumClass;
   private Map<Enum, Class<Param<?>>[]> paramsDef;
 
   public ParametersProvider(String driverParam, Class<? extends Enum> enumClass,
-                            Map<Enum, Class<Param<?>>[]> paramsDef) {
+      Map<Enum, Class<Param<?>>[]> paramsDef) {
     this.driverParam = driverParam;
     this.enumClass = enumClass;
     this.paramsDef = paramsDef;
   }
 
-  @Override
-  @SuppressWarnings("unchecked")
-  public Parameters getValue(HttpContext httpContext) {
-    Map<String, List<Param<?>>> map = new HashMap<String, List<Param<?>>>();
-    Map<String, List<String>> queryString =
-      httpContext.getRequest().getQueryParameters();
-    String str = ((MultivaluedMap<String, String>) queryString).
-        getFirst(driverParam);
+  private Param<?> newParam(Class<Param<?>> paramClass) {
+    try {
+      return paramClass.newInstance();
+    } catch (Exception ex) {
+      throw new UnsupportedOperationException(
+        MessageFormat.format("Param class [{0}] does not have default constructor",
+            paramClass.getName()));
+    }
+  }
+
+  public Parameters get(HttpServletRequest request) {
+    Map<String, List<Param<?>>> map = new HashMap<>();
+
+    Map<String, String[]> queryString = request.getParameterMap();
+    String str = null;
+    if(queryString.containsKey(driverParam)) {
+      str = queryString.get(driverParam)[0];
+    }
     if (str == null) {
       throw new IllegalArgumentException(
         MessageFormat.format("Missing Operation parameter [{0}]",
@@ -83,7 +83,7 @@ public class ParametersProvider
     for (Class<Param<?>> paramClass : paramsDef.get(op)) {
       Param<?> param = newParam(paramClass);
       List<Param<?>> paramList = Lists.newArrayList();
-      List<String> ps = queryString.get(param.getName());
+      String[] ps = queryString.get(param.getName());
       if (ps != null) {
         for (String p : ps) {
           try {
@@ -103,25 +103,4 @@ public class ParametersProvider
     }
     return new Parameters(map);
   }
-
-  private Param<?> newParam(Class<Param<?>> paramClass) {
-    try {
-      return paramClass.newInstance();
-    } catch (Exception ex) {
-      throw new UnsupportedOperationException(
-        MessageFormat.format(
-          "Param class [{0}] does not have default constructor",
-          paramClass.getName()));
-    }
-  }
-
-  @Override
-  public ComponentScope getScope() {
-    return ComponentScope.PerRequest;
-  }
-
-  @Override
-  public Injectable getInjectable(ComponentContext componentContext, Context context, Type type) {
-    return (type.equals(Parameters.class)) ? this : null;
-  }
 }

+ 3 - 15
hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/resources/webapps/webhdfs/WEB-INF/web.xml

@@ -20,23 +20,11 @@
 
   <servlet>
     <servlet-name>webservices-driver</servlet-name>
-    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
     <init-param>
-      <param-name>com.sun.jersey.config.property.packages</param-name>
-      <param-value>org.apache.hadoop.fs.http.server,org.apache.hadoop.lib.wsrs</param-value>
+      <param-name>jersey.config.server.provider.packages</param-name>
+      <param-value>org.apache.hadoop.fs.http.server, org.apache.hadoop.lib.wsrs</param-value>
     </init-param>
-
-    <!-- Enables detailed Jersey request/response logging -->
-    <!--
-            <init-param>
-                <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
-                <param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
-            </init-param>
-            <init-param>
-                <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
-                <param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
-            </init-param>
-    -->
     <load-on-startup>1</load-on-startup>
   </servlet>
 

+ 3 - 15
hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/webapp/WEB-INF/web.xml

@@ -20,23 +20,11 @@
 
   <servlet>
     <servlet-name>webservices-driver</servlet-name>
-    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
     <init-param>
-      <param-name>com.sun.jersey.config.property.packages</param-name>
-      <param-value>org.apache.hadoop.fs.http.server,org.apache.hadoop.lib.wsrs</param-value>
+      <param-name>jersey.config.server.provider.packages</param-name>
+      <param-value>org.apache.hadoop.fs.http.server, org.apache.hadoop.lib.wsrs</param-value>
     </init-param>
-
-    <!-- Enables detailed Jersey request/response logging -->
-    <!--
-            <init-param>
-                <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
-                <param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
-            </init-param>
-            <init-param>
-                <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
-                <param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
-            </init-param>
-    -->
     <load-on-startup>1</load-on-startup>
   </servlet>
 

+ 1 - 2
hadoop-hdfs-project/hadoop-hdfs-httpfs/src/test/java/org/apache/hadoop/fs/http/server/TestHttpFSServer.java

@@ -2001,8 +2001,7 @@ public class TestHttpFSServer extends HFSTestCase {
     conn.connect();
 
     LambdaTestUtils.intercept(IOException.class,
-        "Content-Type \"text/html;charset=iso-8859-1\" "
-            + "is incompatible with \"application/json\"",
+        "java.io.IOException: Server returned HTTP response code: 500 for URL",
         () -> HttpFSUtils.jsonParse(conn));
     conn.disconnect();
   }

+ 0 - 1
hadoop-hdfs-project/hadoop-hdfs-httpfs/src/test/resources/default-log4j.properties

@@ -23,4 +23,3 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 log4j.appender.stdout.Target=System.out
 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{1} - %m%n
-log4j.logger.com.sun.jersey.server.wadl.generators.AbstractWadlGeneratorGrammarGenerator=OFF

+ 5 - 5
hadoop-hdfs-project/hadoop-hdfs-nfs/pom.xml

@@ -109,12 +109,12 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
-      <artifactId>jersey-core</artifactId>
+      <groupId>org.glassfish.jersey.core</groupId>
+      <artifactId>jersey-common</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
+      <groupId>org.glassfish.jersey.core</groupId>
       <artifactId>jersey-server</artifactId>
       <scope>compile</scope>
     </dependency>
@@ -149,8 +149,8 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <scope>${transient.protobuf2.scope}</scope>
     </dependency>
     <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
+      <groupId>jakarta.servlet</groupId>
+      <artifactId>jakarta.servlet-api</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>

+ 5 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/pom.xml

@@ -197,6 +197,11 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <artifactId>junit-platform-launcher</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.codehaus.jettison</groupId>
+      <artifactId>jettison</artifactId>
+      <scope>compile</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 0 - 3
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterWebHdfsMethods.java

@@ -37,9 +37,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-import com.sun.jersey.spi.container.ResourceFilters;
 import org.apache.hadoop.hdfs.web.JsonUtil;
-import org.apache.hadoop.hdfs.web.ParamFilter;
 import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
 import org.apache.hadoop.hdfs.web.resources.AccessTimeParam;
 import org.apache.hadoop.hdfs.web.resources.AclPermissionParam;
@@ -118,7 +116,6 @@ import java.util.regex.Pattern;
  * {@link NamenodeWebHdfsMethods}, and tries to reuse as much as possible.
  */
 @Path("")
-@ResourceFilters(ParamFilter.class)
 public class RouterWebHdfsMethods extends NamenodeWebHdfsMethods {
   private static final Logger LOG =
       LoggerFactory.getLogger(RouterWebHdfsMethods.class);

+ 19 - 5
hadoop-hdfs-project/hadoop-hdfs/pom.xml

@@ -93,15 +93,29 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
-      <artifactId>jersey-core</artifactId>
+      <groupId>org.glassfish.jersey.core</groupId>
+      <artifactId>jersey-common</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey</groupId>
+      <groupId>org.glassfish.jersey.core</groupId>
       <artifactId>jersey-server</artifactId>
       <scope>compile</scope>
     </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.inject</groupId>
+      <artifactId>jersey-hk2</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.media</groupId>
+      <artifactId>jersey-media-json-jettison</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>jakarta.xml.bind</groupId>
+      <artifactId>jakarta.xml.bind-api</artifactId>
+    </dependency>
     <dependency>
       <groupId>commons-cli</groupId>
       <artifactId>commons-cli</artifactId>
@@ -133,8 +147,8 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <scope>${transient.protobuf2.scope}</scope>
     </dependency>
     <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
+      <groupId>jakarta.servlet</groupId>
+      <artifactId>jakarta.servlet-api</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>

+ 2 - 2
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/web/webhdfs/ExceptionHandler.java

@@ -17,8 +17,8 @@
  */
 package org.apache.hadoop.hdfs.server.datanode.web.webhdfs;
 
-import com.sun.jersey.api.ParamException;
-import com.sun.jersey.api.container.ContainerException;
+import org.glassfish.jersey.server.ParamException;
+import org.glassfish.jersey.server.ContainerException;
 import io.netty.buffer.Unpooled;
 import io.netty.handler.codec.http.DefaultFullHttpResponse;
 import io.netty.handler.codec.http.HttpResponseStatus;

+ 22 - 5
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNodeHttpServer.java

@@ -39,16 +39,21 @@ import org.apache.hadoop.hdfs.server.common.JspHelper;
 import org.apache.hadoop.hdfs.server.common.TokenVerifier;
 import org.apache.hadoop.hdfs.server.namenode.startupprogress.StartupProgress;
 import org.apache.hadoop.hdfs.server.namenode.web.resources.NamenodeWebHdfsMethods;
+import org.apache.hadoop.hdfs.web.ParamFilter;
 import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
 import org.apache.hadoop.hdfs.web.resources.AclPermissionParam;
+import org.apache.hadoop.hdfs.web.resources.ExceptionHandler;
 import org.apache.hadoop.hdfs.web.resources.Param;
 import org.apache.hadoop.hdfs.web.resources.UserParam;
+import org.apache.hadoop.hdfs.web.resources.UserProvider;
 import org.apache.hadoop.http.HttpConfig;
 import org.apache.hadoop.http.HttpServer2;
 import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.security.http.RestCsrfPreventionFilter;
 
-import com.sun.jersey.api.core.ResourceConfig;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
 
 /**
  * Encapsulates the HTTP server started by the NameNode. 
@@ -99,12 +104,24 @@ public class NameNodeHttpServer {
           new String[] {pathSpec});
     }
 
+    // add a filter to change parameter names to lower cases
+    HttpServer2.defineFilter(httpServer2.getWebAppContext(),
+        ParamFilter.class.getName(), ParamFilter.class.getName(), null,
+        new String[] {pathSpec});
+
     // add webhdfs packages
     final Map<String, String> params = new HashMap<>();
-    params.put(ResourceConfig.FEATURE_MATCH_MATRIX_PARAMS, "true");
-    httpServer2.addJerseyResourcePackage(
-        jerseyResourcePackage + ";" + Param.class.getPackage().getName(),
-        pathSpec, params);
+    ResourceConfig config = new ResourceConfig();
+    config.register(ExceptionHandler.class);
+    config.packages(jerseyResourcePackage, Param.class.getPackage().getName());
+    config.register(new AbstractBinder() {
+      // add a factory to generate UserGroupInformation
+      @Override
+      protected void configure() {
+        bindFactory(UserProvider.class).to(UserGroupInformation.class);
+      }
+    });
+    httpServer2.addJerseyResourceConfig(config, pathSpec, params);
   }
 
   /**

+ 242 - 43
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/web/resources/NamenodeWebHdfsMethods.java

@@ -58,6 +58,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.StreamingOutput;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
 
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.InvalidPathException;
@@ -108,7 +109,6 @@ import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
 import org.apache.hadoop.hdfs.server.namenode.NameNode;
 import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols;
 import org.apache.hadoop.hdfs.web.JsonUtil;
-import org.apache.hadoop.hdfs.web.ParamFilter;
 import org.apache.hadoop.hdfs.web.WebHdfsConstants;
 import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
 import org.apache.hadoop.hdfs.web.resources.*;
@@ -126,11 +126,9 @@ import org.apache.hadoop.util.Lists;
 import org.apache.hadoop.util.StringUtils;
 
 import org.apache.hadoop.classification.VisibleForTesting;
-import com.sun.jersey.spi.container.ResourceFilters;
 
 /** Web-hdfs NameNode implementation. */
 @Path("")
-@ResourceFilters(ParamFilter.class)
 public class NamenodeWebHdfsMethods {
   public static final Logger LOG =
       LoggerFactory.getLogger(NamenodeWebHdfsMethods.class);
@@ -473,14 +471,46 @@ public class NamenodeWebHdfsMethods {
     return uri;
   }
 
-  /** Handle HTTP PUT request for the root. */
+  /**
+   * Handle HTTP PUT request for the root.
+   *
+   * @param ugi User and group information for Hadoop.
+   * @param uriInfo An injectable interface that provides access.
+   * to application and request URI information.
+   * @param delegation Represents delegation token used for authentication.
+   * @param username User parameter.
+   * @param doAsUser DoAs parameter for proxy user.
+   * @param op Http POST operation parameter.
+   * @param destination Destination path parameter.
+   * @param owner Owner parameter.
+   * @param group Group parameter.
+   * @param permission Permission parameter,
+   * use a Short to represent a FsPermission.
+   * @param unmaskedPermission Unmasked permission parameter,
+   * use a Short to represent a FsPermission.
+   * @param overwrite Overwrite parameter.
+   * @param bufferSize Buffer size parameter.
+   * @param replication Replication parameter.
+   * @param blockSize Block size parameter.
+   * @param modificationTime Modification time parameter.
+   * @param accessTime Access time parameter.
+   * @param renameOptions Rename option set parameter.
+   * @param createFlagParam CreateFlag enum.
+   * @param noredirect Overwrite parameter.
+   * @param policyName policy parameter.
+   * @param ecpolicy policy parameter.
+   * @param namespaceQuota The name space quota parameter for directory.
+   * @param storagespaceQuota The storage space quota parameter for directory.
+   * @param storageType storage type parameter.
+   * @return Represents an HTTP response.
+   */
   @PUT
-  @Path("/")
   @Consumes({"*/*"})
   @Produces({MediaType.APPLICATION_OCTET_STREAM + "; " + JettyUtils.UTF_8,
       MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8})
   public Response putRoot(
       @Context final UserGroupInformation ugi,
+      @Context final UriInfo uriInfo,
       @QueryParam(DelegationParam.NAME) @DefaultValue(DelegationParam.DEFAULT)
           final DelegationParam delegation,
       @QueryParam(UserParam.NAME) @DefaultValue(UserParam.DEFAULT)
@@ -539,7 +569,7 @@ public class NamenodeWebHdfsMethods {
       @QueryParam(StoragePolicyParam.NAME) @DefaultValue(StoragePolicyParam
           .DEFAULT) final StoragePolicyParam policyName,
       @QueryParam(ECPolicyParam.NAME) @DefaultValue(ECPolicyParam
-              .DEFAULT) final ECPolicyParam ecpolicy,
+          .DEFAULT) final ECPolicyParam ecpolicy,
       @QueryParam(NameSpaceQuotaParam.NAME)
       @DefaultValue(NameSpaceQuotaParam.DEFAULT)
       final NameSpaceQuotaParam namespaceQuota,
@@ -550,7 +580,7 @@ public class NamenodeWebHdfsMethods {
       @DefaultValue(StorageTypeParam.DEFAULT)
       final StorageTypeParam storageType
   ) throws IOException, InterruptedException {
-    return put(ugi, delegation, username, doAsUser, ROOT, op, destination,
+    return put(ugi, uriInfo, delegation, username, doAsUser, op, destination,
         owner, group, permission, unmaskedPermission, overwrite, bufferSize,
         replication, blockSize, modificationTime, accessTime, renameOptions,
         createParent, delegationTokenArgument, aclPermission, xattrName,
@@ -571,7 +601,51 @@ public class NamenodeWebHdfsMethods {
     }
   }
 
-  /** Handle HTTP PUT request. */
+  /**
+   * Handle HTTP PUT request.
+   *
+   * @param ugi User and group information for Hadoop.
+   * @param uriInfo An injectable interface that provides access.
+   * @param delegation Represents delegation token used for authentication.
+   * @param username User parameter.
+   * @param doAsUser DoAs parameter for proxy user.
+   * @param op Http POST operation parameter.
+   * @param destination Destination path parameter.
+   * @param owner Owner parameter.
+   * @param group Group parameter.
+   * @param permission Permission parameter,
+   * use a Short to represent a FsPermission.
+   * @param unmaskedPermission Unmasked permission parameter,
+   * use a Short to represent a FsPermission.
+   * @param overwrite Overwrite parameter.
+   * @param bufferSize Buffer size parameter.
+   * @param replication Replication parameter.
+   * @param blockSize Block size parameter.
+   * @param modificationTime Modification time parameter.
+   * @param accessTime Access time parameter.
+   * @param renameOptions Rename option set parameter.
+   * @param createParent Create Parent parameter.
+   * @param delegationTokenArgument Represents delegation token parameter as method arguments.
+   * @param aclPermission AclPermission parameter.
+   * @param xattrName  XAttr Name parameter.
+   * @param xattrValue  XAttr Value parameter.
+   * @param xattrSetFlag XAttr SetFlag parameter.
+   * @param snapshotName The snapshot name parameter
+   * for createSnapshot and deleteSnapshot operation.
+   * @param oldSnapshotName The old snapshot name parameter for renameSnapshot operation.
+   * @param excludeDatanodes Exclude datanodes param.
+   * @param createFlagParam CreateFlag enum.
+   * @param noredirect Overwrite parameter.
+   * @param policyName policy parameter.
+   * @param ecpolicy ec policy parameter.
+   * @param namespaceQuota The name space quota parameter for directory.
+   * @param storagespaceQuota The storage space quota parameter for directory.
+   * @param storageType storage type parameter.
+   * @return Represents an HTTP response.
+   * @throws IOException any IOE raised, or translated exception.
+   * @throws InterruptedException if the current thread was interrupted
+   * before or during the call.
+   */
   @PUT
   @Path("{" + UriFsPathParam.NAME + ":.*}")
   @Consumes({"*/*"})
@@ -579,13 +653,13 @@ public class NamenodeWebHdfsMethods {
       MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8})
   public Response put(
       @Context final UserGroupInformation ugi,
+      @Context final UriInfo uriInfo,
       @QueryParam(DelegationParam.NAME) @DefaultValue(DelegationParam.DEFAULT)
           final DelegationParam delegation,
       @QueryParam(UserParam.NAME) @DefaultValue(UserParam.DEFAULT)
           final UserParam username,
       @QueryParam(DoAsParam.NAME) @DefaultValue(DoAsParam.DEFAULT)
           final DoAsParam doAsUser,
-      @PathParam(UriFsPathParam.NAME) final UriFsPathParam path,
       @QueryParam(PutOpParam.NAME) @DefaultValue(PutOpParam.DEFAULT)
           final PutOpParam op,
       @QueryParam(DestinationParam.NAME) @DefaultValue(DestinationParam.DEFAULT)
@@ -648,6 +722,7 @@ public class NamenodeWebHdfsMethods {
       @QueryParam(StorageTypeParam.NAME) @DefaultValue(StorageTypeParam.DEFAULT)
           final StorageTypeParam storageType
       ) throws IOException, InterruptedException {
+    final UriFsPathParam path = new UriFsPathParam(uriInfo.getPath());
     init(ugi, delegation, username, doAsUser, path, op, destination, owner,
         group, permission, unmaskedPermission, overwrite, bufferSize,
         replication, blockSize, modificationTime, accessTime, renameOptions,
@@ -895,13 +970,29 @@ public class NamenodeWebHdfsMethods {
           StorageType.parseStorageType(storageType.getValue()));
       return Response.ok().type(MediaType.APPLICATION_OCTET_STREAM).build();
     default:
-      throw new UnsupportedOperationException(op + " is not supported");
+      throw new UnsupportedOperationException(op + "  is not supported");
     }
   }
 
-  /** Handle HTTP POST request for the root. */
+  /**
+   * Handle HTTP POST request for the root.
+   *
+   * @param ugi User and group information for Hadoop.
+   * @param delegation Represents delegation token used for authentication.
+   * @param username User parameter.
+   * @param doAsUser DoAs parameter for proxy user.
+   * @param op Http POST operation parameter.
+   * @param concatSrcs The concat source paths parameter.
+   * @param bufferSize Buffer size parameter.
+   * @param excludeDatanodes Exclude datanodes param.
+   * @param newLength NewLength parameter.
+   * @param noredirect Overwrite parameter.
+   * @return Represents an HTTP response.
+   * @throws IOException any IOE raised, or translated exception.
+   * @throws InterruptedException if the current thread was interrupted
+   * before or during the call.
+   */
   @POST
-  @Path("/")
   @Consumes({"*/*"})
   @Produces({MediaType.APPLICATION_OCTET_STREAM + "; " + JettyUtils.UTF_8,
       MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8})
@@ -930,7 +1021,25 @@ public class NamenodeWebHdfsMethods {
         bufferSize, excludeDatanodes, newLength, noredirect);
   }
 
-  /** Handle HTTP POST request. */
+  /**
+   * Handle HTTP POST request.
+   *
+   * @param ugi User and group information for Hadoop.
+   * @param delegation Represents delegation token used for authentication.
+   * @param username User parameter.
+   * @param doAsUser DoAs parameter for proxy user.
+   * @param path The FileSystem path parameter.
+   * @param op Http POST operation parameter.
+   * @param concatSrcs The concat source paths parameter.
+   * @param bufferSize Buffer size parameter.
+   * @param excludeDatanodes Exclude datanodes param.
+   * @param newLength NewLength parameter.
+   * @param noredirect Overwrite parameter.
+   * @return Represents an HTTP response.
+   * @throws IOException any IOE raised, or translated exception.
+   * @throws InterruptedException if the current thread was interrupted
+   * before or during the call.
+   */
   @POST
   @Path("{" + UriFsPathParam.NAME + ":.*}")
   @Consumes({"*/*"})
@@ -1029,13 +1138,47 @@ public class NamenodeWebHdfsMethods {
     }
   }
 
-  /** Handle HTTP GET request for the root. */
+  /**
+   * Handle HTTP GET request for the root.
+   *
+   * @param ugi User and group information for Hadoop.
+   * @param uriInfo An injectable interface that provides access.
+   * to application and request URI information.
+   * @param delegation Represents delegation token used for authentication.
+   * @param username User parameter.
+   * @param doAsUser DoAs parameter for proxy user.
+   * @param op Http GET operation parameter.
+   * @param offset Offset parameter.
+   * @param length Length parameter.
+   * @param renewer Renewer parameter.
+   * @param bufferSize Buffer size parameter.
+   * @param xattrNames XAttr Name parameter.
+   * @param xattrEncoding Xattr Encoding parameter.
+   * @param excludeDatanodes Exclude datanodes param.
+   * @param fsAction FsAction Parameter.
+   * @param snapshotName
+   * The snapshot name parameter for createSnapshot and deleteSnapshot operation.
+   * @param oldSnapshotName
+   * The old snapshot name parameter for renameSnapshot operation.
+   * @param snapshotDiffStartPath
+   * The snapshot startPath parameter used by snapshotDiffReportListing.
+   * @param snapshotDiffIndex resuming index of snapshotDiffReportListing operation.
+   * @param tokenKind tokenKind Parameter.
+   * @param tokenService TokenService Parameter.
+   * @param noredirect Overwrite parameter.
+   * @param startAfter Used during batched ListStatus operations.
+   * @param allUsers AllUsers parameter.
+   * @return Represents an HTTP response.
+   * @throws IOException any IOE raised, or translated exception.
+   * @throws InterruptedException if the current thread was interrupted
+   * before or during the call.
+   */
   @GET
-  @Path("/")
   @Produces({MediaType.APPLICATION_OCTET_STREAM + "; " + JettyUtils.UTF_8,
       MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8})
   public Response getRoot(
       @Context final UserGroupInformation ugi,
+      @Context final UriInfo uriInfo,
       @QueryParam(DelegationParam.NAME) @DefaultValue(DelegationParam.DEFAULT)
           final DelegationParam delegation,
       @QueryParam(UserParam.NAME) @DefaultValue(UserParam.DEFAULT)
@@ -1079,7 +1222,7 @@ public class NamenodeWebHdfsMethods {
       @QueryParam(AllUsersParam.NAME) @DefaultValue(AllUsersParam.DEFAULT)
           final AllUsersParam allUsers
       ) throws IOException, InterruptedException {
-    return get(ugi, delegation, username, doAsUser, ROOT, op, offset, length,
+    return get(ugi, uriInfo, delegation, username, doAsUser, op, offset, length,
         renewer, bufferSize, xattrNames, xattrEncoding, excludeDatanodes,
         fsAction, snapshotName, oldSnapshotName,
         snapshotDiffStartPath, snapshotDiffIndex,
@@ -1087,20 +1230,54 @@ public class NamenodeWebHdfsMethods {
         noredirect, startAfter, allUsers);
   }
 
-  /** Handle HTTP GET request. */
+  /**
+   * Handle HTTP GET request.
+   *
+   * @param ugi User and group information for Hadoop.
+   * @param uriInfo An injectable interface that provides access.
+   * @param delegation Represents delegation token used for authentication.
+   * @param username User parameter.
+   * @param doAsUser DoAs parameter for proxy user.
+   * @param op Http DELETE operation parameter.
+   * @param offset Offset parameter.
+   * @param length Length parameter.
+   * @param renewer Renewer parameter.
+   * @param bufferSize Buffer size parameter.
+   * @param xattrNames XAttr Name parameter.
+   * @param xattrEncoding Xattr Encoding parameter.
+   * @param excludeDatanodes Exclude datanodes param.
+   * @param fsAction FsAction Parameter.
+   * @param snapshotName
+   * The snapshot name parameter for createSnapshot and deleteSnapshot operation.
+   * @param oldSnapshotName
+   * The old snapshot name parameter for renameSnapshot operation.
+   * @param snapshotDiffStartPath
+   * The snapshot startPath parameter used by snapshotDiffReportListing.
+   * @param snapshotDiffIndex
+   * resuming index of snapshotDiffReportListing operation.
+   * @param tokenKind tokenKind Parameter.
+   * @param tokenService tokenService Parameter.
+   * @param noredirect overwrite parameter.
+   * @param startAfter used during batched ListStatus operations.
+   * @param allUsers AllUsers parameter.
+   * @return Represents an HTTP response.
+   * @throws IOException any IOE raised, or translated exception.
+   * @throws InterruptedException if the current thread was interrupted
+   * before or during the call.
+   */
   @GET
   @Path("{" + UriFsPathParam.NAME + ":.*}")
   @Produces({MediaType.APPLICATION_OCTET_STREAM + "; " + JettyUtils.UTF_8,
       MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8})
   public Response get(
       @Context final UserGroupInformation ugi,
+      @Context final UriInfo uriInfo,
       @QueryParam(DelegationParam.NAME) @DefaultValue(DelegationParam.DEFAULT)
           final DelegationParam delegation,
       @QueryParam(UserParam.NAME) @DefaultValue(UserParam.DEFAULT)
           final UserParam username,
       @QueryParam(DoAsParam.NAME) @DefaultValue(DoAsParam.DEFAULT)
           final DoAsParam doAsUser,
-      @PathParam(UriFsPathParam.NAME) final UriFsPathParam path,
       @QueryParam(GetOpParam.NAME) @DefaultValue(GetOpParam.DEFAULT)
           final GetOpParam op,
       @QueryParam(OffsetParam.NAME) @DefaultValue(OffsetParam.DEFAULT)
@@ -1139,20 +1316,16 @@ public class NamenodeWebHdfsMethods {
           final AllUsersParam allUsers
       ) throws IOException, InterruptedException {
 
+    final UriFsPathParam path = new UriFsPathParam(uriInfo.getPath());
     init(ugi, delegation, username, doAsUser, path, op, offset, length,
         renewer, bufferSize, xattrEncoding, excludeDatanodes, fsAction,
         snapshotName, oldSnapshotName, tokenKind, tokenService, startAfter, allUsers);
 
-    return doAs(ugi, new PrivilegedExceptionAction<Response>() {
-      @Override
-      public Response run() throws IOException, URISyntaxException {
-        return get(ugi, delegation, username, doAsUser, path.getAbsolutePath(),
-            op, offset, length, renewer, bufferSize, xattrNames, xattrEncoding,
-            excludeDatanodes, fsAction, snapshotName, oldSnapshotName,
-            snapshotDiffStartPath, snapshotDiffIndex,
-            tokenKind, tokenService, noredirect, startAfter, allUsers);
-      }
-    });
+    return doAs(ugi, () -> get(ugi, delegation, username, doAsUser, path.getAbsolutePath(),
+        op, offset, length, renewer, bufferSize, xattrNames, xattrEncoding,
+        excludeDatanodes, fsAction, snapshotName, oldSnapshotName,
+        snapshotDiffStartPath, snapshotDiffIndex,
+        tokenKind, tokenService, noredirect, startAfter, allUsers));
   }
 
   private static String encodeFeInfo(FileEncryptionInfo feInfo) {
@@ -1449,7 +1622,7 @@ public class NamenodeWebHdfsMethods {
    * /snapdir1/path/to/file, this method would return /snapdir1
    * @param pathStr String of path to a file or a directory.
    * @return Not null if found in a snapshot root directory.
-   * @throws IOException
+   * @throws IOException any IOE raised, or translated exception.
    */
   String getSnapshotRoot(String pathStr) throws IOException {
     SnapshottableDirectoryStatus[] dirStatusList =
@@ -1584,12 +1757,30 @@ public class NamenodeWebHdfsMethods {
   }
 
 
-  /** Handle HTTP DELETE request for the root. */
+  /**
+   * Handle HTTP DELETE request for the root.
+   *
+   * @param ugi User and group information for Hadoop.
+   * @param uriInfo An injectable interface that provides access.
+   * to application and request URI information.
+   * @param delegation Represents delegation token used for authentication.
+   * @param username User parameter.
+   * @param doAsUser DoAs parameter for proxy user.
+   * @param op Http DELETE operation parameter.
+   * @param recursive Recursive parameter.
+   * @param snapshotName The snapshot name parameter for createSnapshot.
+   * and deleteSnapshot operation.
+   * @return Represents an HTTP response.
+   * @throws IOException any IOE raised, or translated exception.
+   * @throws InterruptedException if the current thread was interrupted
+   * before or during the call.
+   */
   @DELETE
-  @Path("/")
   @Produces(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8)
+  @SuppressWarnings("checkstyle:ParameterNumber")
   public Response deleteRoot(
       @Context final UserGroupInformation ugi,
+      @Context final UriInfo uriInfo,
       @QueryParam(DelegationParam.NAME) @DefaultValue(DelegationParam.DEFAULT)
           final DelegationParam delegation,
       @QueryParam(UserParam.NAME) @DefaultValue(UserParam.DEFAULT)
@@ -1603,23 +1794,36 @@ public class NamenodeWebHdfsMethods {
       @QueryParam(SnapshotNameParam.NAME) @DefaultValue(SnapshotNameParam.DEFAULT)
           final SnapshotNameParam snapshotName
       ) throws IOException, InterruptedException {
-    return delete(ugi, delegation, username, doAsUser, ROOT, op, recursive,
-        snapshotName);
+    return delete(ugi, uriInfo, delegation, username, doAsUser, op, recursive, snapshotName);
   }
 
-  /** Handle HTTP DELETE request. */
+  /**
+   * Handle HTTP DELETE request.
+   *
+   * @param ugi User and group information for Hadoop.
+   * @param uriInfo An injectable interface that provides access.
+   * to application and request URI information.
+   * @param delegation Represents delegation token used for authentication.
+   * @param username User parameter.
+   * @param doAsUser DoAs parameter for proxy user.
+   * @param op Http DELETE operation parameter.
+   * @param recursive Recursive parameter.
+   * @param snapshotName The snapshot name parameter for createSnapshot
+   * and deleteSnapshot operation.
+   * @return Represents an HTTP response.
+   */
   @DELETE
   @Path("{" + UriFsPathParam.NAME + ":.*}")
   @Produces(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8)
   public Response delete(
       @Context final UserGroupInformation ugi,
+      @Context final UriInfo uriInfo,
       @QueryParam(DelegationParam.NAME) @DefaultValue(DelegationParam.DEFAULT)
           final DelegationParam delegation,
       @QueryParam(UserParam.NAME) @DefaultValue(UserParam.DEFAULT)
           final UserParam username,
       @QueryParam(DoAsParam.NAME) @DefaultValue(DoAsParam.DEFAULT)
           final DoAsParam doAsUser,
-      @PathParam(UriFsPathParam.NAME) final UriFsPathParam path,
       @QueryParam(DeleteOpParam.NAME) @DefaultValue(DeleteOpParam.DEFAULT)
           final DeleteOpParam op,
       @QueryParam(RecursiveParam.NAME) @DefaultValue(RecursiveParam.DEFAULT)
@@ -1627,16 +1831,11 @@ public class NamenodeWebHdfsMethods {
       @QueryParam(SnapshotNameParam.NAME) @DefaultValue(SnapshotNameParam.DEFAULT)
           final SnapshotNameParam snapshotName
       ) throws IOException, InterruptedException {
-
+    final UriFsPathParam path = new UriFsPathParam(uriInfo.getPath());
     init(ugi, delegation, username, doAsUser, path, op, recursive, snapshotName);
 
-    return doAs(ugi, new PrivilegedExceptionAction<Response>() {
-      @Override
-      public Response run() throws IOException {
-          return delete(ugi, delegation, username, doAsUser,
-              path.getAbsolutePath(), op, recursive, snapshotName);
-      }
-    });
+    return doAs(ugi, () -> delete(ugi, delegation, username, doAsUser,
+        path.getAbsolutePath(), op, recursive, snapshotName));
   }
 
   protected Response delete(

+ 57 - 46
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/web/ParamFilter.java

@@ -17,70 +17,81 @@
  */
 package org.apache.hadoop.hdfs.web;
 
-import java.net.URI;
-import java.util.List;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Map;
+import java.io.IOException;
 
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.UriBuilder;
-
-import com.sun.jersey.spi.container.ContainerRequest;
-import com.sun.jersey.spi.container.ContainerRequestFilter;
-import com.sun.jersey.spi.container.ContainerResponseFilter;
-import com.sun.jersey.spi.container.ResourceFilter;
-import org.apache.hadoop.util.StringUtils;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
 
 /**
  * A filter to change parameter names to lower cases
  * so that parameter names are considered as case insensitive.
  */
-public class ParamFilter implements ResourceFilter {
-  private static final ContainerRequestFilter LOWER_CASE
-      = new ContainerRequestFilter() {
-    @Override
-    public ContainerRequest filter(final ContainerRequest request) {
-      final MultivaluedMap<String, String> parameters = request.getQueryParameters();
-      if (containsUpperCase(parameters.keySet())) {
-        //rebuild URI
-        final URI lower = rebuildQuery(request.getRequestUri(), parameters);
-        request.setUris(request.getBaseUri(), lower);
-      }
-      return request;
-    }
-  };
+public class ParamFilter implements Filter {
+
+  @Override
+  public void init(FilterConfig filterConfig) throws ServletException {
+  }
 
   @Override
-  public ContainerRequestFilter getRequestFilter() {
-    return LOWER_CASE;
+  public void doFilter(ServletRequest request, ServletResponse response,
+      FilterChain chain) throws IOException, ServletException {
+    if (request instanceof HttpServletRequest) {
+      HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+      chain.doFilter(new CustomHttpServletRequestWrapper(httpServletRequest), response);
+    } else {
+      chain.doFilter(request, response);
+    }
   }
 
   @Override
-  public ContainerResponseFilter getResponseFilter() {
-    return null;
+  public void destroy() {
   }
 
-  /** Do the strings contain upper case letters? */
-  static boolean containsUpperCase(final Iterable<String> strings) {
-    for(String s : strings) {
-      for(int i = 0; i < s.length(); i++) {
-        if (Character.isUpperCase(s.charAt(i))) {
-          return true;
-        }
+  private static final class CustomHttpServletRequestWrapper
+      extends HttpServletRequestWrapper {
+
+    private Map<String, String[]> lowerCaseParams = new HashMap<>();
+
+    private CustomHttpServletRequestWrapper(HttpServletRequest request) {
+      super(request);
+      Map<String, String[]> originalParams = request.getParameterMap();
+      for (Map.Entry<String, String[]> entry : originalParams.entrySet()) {
+        lowerCaseParams.put(entry.getKey().toLowerCase(), entry.getValue());
       }
     }
-    return false;
-  }
 
-  /** Rebuild the URI query with lower case parameter names. */
-  private static URI rebuildQuery(final URI uri,
-      final MultivaluedMap<String, String> parameters) {
-    UriBuilder b = UriBuilder.fromUri(uri).replaceQuery("");
-    for(Map.Entry<String, List<String>> e : parameters.entrySet()) {
-      final String key = StringUtils.toLowerCase(e.getKey());
-      for(String v : e.getValue()) {
-        b = b.queryParam(key, v);
+    public String getParameter(String name) {
+      String[] values = getParameterValues(name);
+      if (values != null && values.length > 0) {
+        return values[0];
+      } else {
+        return null;
       }
     }
-    return b.build();
+
+    @Override
+    public Map<String, String[]> getParameterMap() {
+      return Collections.unmodifiableMap(lowerCaseParams);
+    }
+
+    @Override
+    public Enumeration<String> getParameterNames() {
+      return Collections.enumeration(lowerCaseParams.keySet());
+    }
+
+    @Override
+    public String[] getParameterValues(String name) {
+      return lowerCaseParams.get(name.toLowerCase());
+    }
   }
 }

+ 9 - 2
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/web/resources/ExceptionHandler.java

@@ -36,8 +36,9 @@ import org.apache.hadoop.security.authorize.AuthorizationException;
 import org.apache.hadoop.security.token.SecretManager.InvalidToken;
 
 import org.apache.hadoop.classification.VisibleForTesting;
-import com.sun.jersey.api.ParamException;
-import com.sun.jersey.api.container.ContainerException;
+import org.glassfish.jersey.server.ContainerException;
+import org.glassfish.jersey.server.ParamException;
+import org.glassfish.hk2.api.MultiException;
 
 /** Handle exceptions. */
 @Provider
@@ -94,6 +95,10 @@ public class ExceptionHandler implements ExceptionMapper<Exception> {
     if (e instanceof SecurityException) {
       e = toCause(e);
     }
+
+    if(e instanceof MultiException) {
+      e = toCause(e);
+    }
     
     //Map response status
     final Response.Status s;
@@ -109,6 +114,8 @@ public class ExceptionHandler implements ExceptionMapper<Exception> {
       s = Response.Status.BAD_REQUEST;
     } else if (e instanceof IllegalArgumentException) {
       s = Response.Status.BAD_REQUEST;
+    } else if (e instanceof MultiException) {
+      s = Response.Status.FORBIDDEN;
     } else {
       LOG.warn("INTERNAL_SERVER_ERROR", e);
       s = Response.Status.INTERNAL_SERVER_ERROR;

+ 0 - 2
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/web/resources/TokenServiceParam.java

@@ -18,8 +18,6 @@
 
 package org.apache.hadoop.hdfs.web.resources;
 
-import org.apache.hadoop.hdfs.web.resources.StringParam;
-
 public class TokenServiceParam extends StringParam {
 
   /** Parameter name */

+ 8 - 27
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/web/resources/UserProvider.java

@@ -18,7 +18,7 @@
 package org.apache.hadoop.hdfs.web.resources;
 
 import java.io.IOException;
-import java.lang.reflect.Type;
+import java.util.function.Supplier;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -31,23 +31,16 @@ import org.apache.hadoop.security.SecurityUtil;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
 
-import com.sun.jersey.api.core.HttpContext;
-import com.sun.jersey.core.spi.component.ComponentContext;
-import com.sun.jersey.core.spi.component.ComponentScope;
-import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable;
-import com.sun.jersey.spi.inject.Injectable;
-import com.sun.jersey.spi.inject.InjectableProvider;
-
 /** Inject user information to http operations. */
 @Provider
-public class UserProvider
-    extends AbstractHttpContextInjectable<UserGroupInformation>
-    implements InjectableProvider<Context, Type> {
-  @Context HttpServletRequest request;
-  @Context ServletContext servletcontext;
+public class UserProvider implements Supplier<UserGroupInformation> {
+  @Context
+  private HttpServletRequest request;
+
+  @Context
+  private ServletContext servletcontext;
 
-  @Override
-  public UserGroupInformation getValue(final HttpContext context) {
+  public UserGroupInformation get() {
     final Configuration conf = (Configuration) servletcontext
         .getAttribute(JspHelper.CURRENT_CONF);
     try {
@@ -58,16 +51,4 @@ public class UserProvider
           SecurityUtil.FAILED_TO_GET_UGI_MSG_HEADER + " " + e, e);
     }
   }
-
-  @Override
-  public ComponentScope getScope() {
-    return ComponentScope.PerRequest;
-  }
-
-  @Override
-  public Injectable<UserGroupInformation> getInjectable(
-      final ComponentContext componentContext, final Context context,
-      final Type type) {
-    return type.equals(UserGroupInformation.class)? this : null;
-  }
 }

+ 5 - 5
hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/web/TestWebHdfsFileSystemContract.java

@@ -165,20 +165,20 @@ public class TestWebHdfsFileSystemContract extends FileSystemContractBaseTest {
   }
 
   @Test
-  public void testCaseInsensitive() throws IOException {
+  public void testCaseInsensitive() throws IOException, InterruptedException {
     final Path p = new Path("/test/testCaseInsensitive");
-    final WebHdfsFileSystem webhdfs = (WebHdfsFileSystem)fs;
+    final WebHdfsFileSystem webhdfs = (WebHdfsFileSystem) fs;
     final PutOpParam.Op op = PutOpParam.Op.MKDIRS;
 
     //replace query with mix case letters
     final URL url = webhdfs.toUrl(op, p);
     WebHdfsFileSystem.LOG.info("url      = " + url);
+    // TODO: Jersey2 Not support url change,
     final URL replaced = new URL(url.toString().replace(op.toQueryString(),
-        "Op=mkDIrs"));
+        "op=mkDIrs"));
     WebHdfsFileSystem.LOG.info("replaced = " + replaced);
-
     //connect with the replaced URL.
-    final HttpURLConnection conn = (HttpURLConnection)replaced.openConnection();
+    final HttpURLConnection conn = (HttpURLConnection) replaced.openConnection();
     conn.setRequestMethod(op.getType().toString());
     conn.connect();
     final BufferedReader in = new BufferedReader(new InputStreamReader(

+ 0 - 4
hadoop-hdfs-project/hadoop-hdfs/src/test/resources/log4j.properties

@@ -57,10 +57,6 @@ log4j.appender.ASYNCDNMETRICSRFA.maxFileSize=64MB
 log4j.appender.ASYNCDNMETRICSRFA.fileName=${hadoop.log.dir}/datanode-metrics.log
 log4j.appender.ASYNCDNMETRICSRFA.maxBackupIndex=1
 
-
-# Supress KMS error log
-log4j.logger.com.sun.jersey.server.wadl.generators.WadlGeneratorJAXBGrammarGenerator=OFF
-
 #
 # hdfs audit logging
 #

+ 44 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/pom.xml

@@ -124,6 +124,50 @@
       <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.test-framework</groupId>
+      <artifactId>jersey-test-framework-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+      <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.inject</groupId>
+      <artifactId>jersey-hk2</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.media</groupId>
+      <artifactId>jersey-media-jaxb</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.media</groupId>
+      <artifactId>jersey-media-json-jettison</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 4 - 4
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/jobhistory/JobHistoryEventHandler.java

@@ -80,7 +80,7 @@ import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
 import org.apache.hadoop.yarn.util.TimelineServiceHelper;
 
 import org.apache.hadoop.classification.VisibleForTesting;
-import com.sun.jersey.api.client.ClientHandlerException;
+import javax.ws.rs.ProcessingException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -1141,9 +1141,9 @@ public class JobHistoryEventHandler extends AbstractService
                   + error.getErrorCode());
         }
       }
-    } catch (YarnException | IOException | ClientHandlerException ex) {
-      LOG.error("Error putting entity " + tEntity.getEntityId() + " to Timeline"
-          + "Server", ex);
+    } catch (YarnException | IOException | ProcessingException ex) {
+      LOG.error("Error putting entity {} to Timeline Server",
+          tEntity.getEntityId(), ex);
     }
   }
 

+ 27 - 1
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/client/MRClientService.java

@@ -78,6 +78,9 @@ import org.apache.hadoop.mapreduce.v2.app.job.event.TaskEvent;
 import org.apache.hadoop.mapreduce.v2.app.job.event.TaskEventType;
 import org.apache.hadoop.mapreduce.v2.app.security.authorize.MRAMPolicyProvider;
 import org.apache.hadoop.mapreduce.v2.app.webapp.AMWebApp;
+import org.apache.hadoop.mapreduce.v2.app.webapp.AMWebServices;
+import org.apache.hadoop.mapreduce.v2.app.webapp.App;
+import org.apache.hadoop.mapreduce.v2.app.webapp.JAXBContextResolver;
 import org.apache.hadoop.net.NetUtils;
 import org.apache.hadoop.security.AccessControlException;
 import org.apache.hadoop.security.UserGroupInformation;
@@ -87,8 +90,12 @@ import org.apache.hadoop.yarn.exceptions.YarnException;
 import org.apache.hadoop.yarn.factories.RecordFactory;
 import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
 import org.apache.hadoop.yarn.ipc.YarnRPC;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
 import org.apache.hadoop.yarn.webapp.WebApp;
 import org.apache.hadoop.yarn.webapp.WebApps;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -149,7 +156,8 @@ public class MRClientService extends AbstractService implements ClientService {
             .withHttpPolicy(conf, httpPolicy)
             .withPortRange(conf, MRJobConfig.MR_AM_WEBAPP_PORT_RANGE)
             .needsClientAuth(needsClientAuth)
-            .start(new AMWebApp());
+            .withResourceConfig(configure())
+            .start(new AMWebApp(appContext));
     } catch (Exception e) {
       LOG.error("Webapps failed to start. Ignoring for now:", e);
     }
@@ -440,4 +448,22 @@ public class MRClientService extends AbstractService implements ClientService {
   public WebApp getWebApp() {
     return webApp;
   }
+
+  protected ResourceConfig configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.packages("org.apache.hadoop.mapreduce.v2.app.webapp");
+    config.register(new JerseyBinder());
+    config.register(AMWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
+
+  private class JerseyBinder extends AbstractBinder {
+    @Override
+    protected void configure() {
+      bind(appContext).to(AppContext.class).named("am");
+      bind(new App(appContext)).to(App.class).named("app");
+    }
+  }
 }

+ 15 - 4
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AMWebApp.java

@@ -20,19 +20,25 @@ package org.apache.hadoop.mapreduce.v2.app.webapp;
 
 import static org.apache.hadoop.yarn.util.StringHelper.pajoin;
 
-import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.mapreduce.v2.app.AppContext;
 import org.apache.hadoop.yarn.webapp.WebApp;
 
+import javax.servlet.Filter;
+
 /**
  * Application master webapp
  */
 public class AMWebApp extends WebApp implements AMParams {
 
+  private AppContext appContext;
+
+  public AMWebApp(AppContext appContext) {
+    this.appContext = appContext;
+  }
+
   @Override
   public void setup() {
-    bind(JAXBContextResolver.class);
-    bind(GenericExceptionHandler.class);
-    bind(AMWebServices.class);
+    bind(AppContext.class).toInstance(appContext);
     route("/", AppController.class);
     route("/app", AppController.class);
     route(pajoin("/job", JOB_ID), AppController.class, "job");
@@ -48,4 +54,9 @@ public class AMWebApp extends WebApp implements AMParams {
     route(pajoin("/singletaskcounter",TASK_ID, COUNTER_GROUP, COUNTER_NAME),
         AppController.class, "singleTaskCounter");
   }
+
+  @Override
+  protected Class<? extends Filter> getWebAppFilterClass() {
+    return null;
+  }
 }

+ 8 - 3
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AMWebServices.java

@@ -23,6 +23,9 @@ import java.lang.reflect.UndeclaredThrowableException;
 import java.security.AccessControlException;
 import java.security.PrivilegedExceptionAction;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.inject.Named;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.Consumes;
@@ -80,18 +83,20 @@ import org.apache.hadoop.yarn.webapp.BadRequestException;
 import org.apache.hadoop.yarn.webapp.NotFoundException;
 
 import org.apache.hadoop.util.Preconditions;
-import com.google.inject.Inject;
 
+
+@Singleton
 @Path("/ws/v1/mapreduce")
 public class AMWebServices {
   private final AppContext appCtx;
   private final App app;
   private final MRClientService service;
 
-  private @Context HttpServletResponse response;
+  @Context
+  private HttpServletResponse response;
   
   @Inject
-  public AMWebServices(final App app, final AppContext context) {
+  public AMWebServices(final @Named("app") App app, final @Named("am") AppContext context) {
     this.appCtx = context;
     this.app = app;
     this.service = new MRClientService(context);

+ 2 - 5
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/App.java

@@ -18,21 +18,18 @@
 
 package org.apache.hadoop.mapreduce.v2.app.webapp;
 
-import com.google.inject.Inject;
-import com.google.inject.servlet.RequestScoped;
-
+import javax.inject.Inject;
 import org.apache.hadoop.mapreduce.v2.app.AppContext;
 import org.apache.hadoop.mapreduce.v2.app.job.Job;
 import org.apache.hadoop.mapreduce.v2.app.job.Task;
 
-@RequestScoped
 public class App {
   final AppContext context;
   private Job job;
   private Task task;
 
   @Inject
-  App(AppContext ctx) {
+  public App(AppContext ctx) {
     context = ctx;
   }
 

+ 5 - 10
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/JAXBContextResolver.java

@@ -21,9 +21,8 @@ package org.apache.hadoop.mapreduce.v2.app.webapp;
 import java.util.HashMap;
 import java.util.Map;
 
-import com.sun.jersey.api.json.JSONConfiguration;
-import com.sun.jersey.api.json.JSONJAXBContext;
-import com.google.inject.Singleton;
+import org.glassfish.jersey.jettison.JettisonJaxbContext;
+import javax.inject.Singleton;
 
 import javax.ws.rs.ext.ContextResolver;
 import javax.ws.rs.ext.Provider;
@@ -72,13 +71,9 @@ public class JAXBContextResolver implements ContextResolver<JAXBContext> {
     JAXBContext context;
     JAXBContext unWrappedRootContext;
 
-    this.typesContextMap = new HashMap<Class, JAXBContext>();
-    context =
-        new JSONJAXBContext(JSONConfiguration.natural().rootUnwrapping(false)
-            .build(), cTypes);
-    unWrappedRootContext =
-        new JSONJAXBContext(JSONConfiguration.natural().rootUnwrapping(true)
-            .build(), rootUnwrappedTypes);
+    this.typesContextMap = new HashMap<>();
+    context = new JettisonJaxbContext(cTypes);
+    unWrappedRootContext = new JettisonJaxbContext(rootUnwrappedTypes);
     for (Class type : cTypes) {
       typesContextMap.put(type, context);
     }

+ 37 - 8
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebApp.java

@@ -40,6 +40,11 @@ import javax.net.ssl.SSLException;
 import org.apache.hadoop.mapreduce.MRJobConfig;
 import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
 import org.apache.hadoop.thirdparty.com.google.common.net.HttpHeaders;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.yarn.webapp.WebApps;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 import org.junit.Assert;
 
 import org.apache.hadoop.conf.Configuration;
@@ -62,7 +67,6 @@ import org.apache.hadoop.net.NetUtils;
 import org.apache.hadoop.yarn.conf.YarnConfiguration;
 import org.apache.hadoop.yarn.server.webproxy.ProxyUriUtils;
 import org.apache.hadoop.yarn.server.webproxy.amfilter.AmFilterInitializer;
-import org.apache.hadoop.yarn.webapp.WebApps;
 import org.apache.hadoop.yarn.webapp.test.WebAppTests;
 import org.apache.hadoop.yarn.webapp.util.WebAppUtils;
 import org.apache.http.HttpStatus;
@@ -208,7 +212,7 @@ public class TestAMWebApp {
         NetUtils.getHostPortString(((MRClientService) app.getClientService())
           .getWebApp().getListenerAddress());
     // http:// should be accessible
-    URL httpUrl = new URL("http://" + hostPort);
+    URL httpUrl = new URL("http://" + hostPort + "/mapreduce/");
     HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();
     InputStream in = conn.getInputStream();
     ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -216,7 +220,7 @@ public class TestAMWebApp {
     Assert.assertTrue(out.toString().contains("MapReduce Application"));
 
     // https:// is not accessible.
-    URL httpsUrl = new URL("https://" + hostPort);
+    URL httpsUrl = new URL("https://" + hostPort + "/mapreduce/");
     try {
       HttpURLConnection httpsConn =
           (HttpURLConnection) httpsUrl.openConnection();
@@ -262,7 +266,7 @@ public class TestAMWebApp {
         NetUtils.getHostPortString(((MRClientService) app.getClientService())
             .getWebApp().getListenerAddress());
     // https:// should be accessible
-    URL httpsUrl = new URL("https://" + hostPort);
+    URL httpsUrl = new URL("https://" + hostPort + "/mapreduce/");
     HttpsURLConnection httpsConn =
         (HttpsURLConnection) httpsUrl.openConnection();
     KeyStoreTestUtil.setAllowAllSSL(httpsConn);
@@ -273,7 +277,7 @@ public class TestAMWebApp {
     Assert.assertTrue(out.toString().contains("MapReduce Application"));
 
     // http:// is not accessible.
-    URL httpUrl = new URL("http://" + hostPort);
+    URL httpUrl = new URL("http://" + hostPort + "/mapreduce/");
     try {
       HttpURLConnection httpConn =
           (HttpURLConnection) httpUrl.openConnection();
@@ -329,7 +333,7 @@ public class TestAMWebApp {
         NetUtils.getHostPortString(((MRClientService) app.getClientService())
             .getWebApp().getListenerAddress());
     // https:// should be accessible
-    URL httpsUrl = new URL("https://" + hostPort);
+    URL httpsUrl = new URL("https://" + hostPort + "/mapreduce/");
     HttpsURLConnection httpsConn =
         (HttpsURLConnection) httpsUrl.openConnection();
     KeyStoreTestUtil.setAllowAllSSL(httpsConn, clientCert, clientKeyPair);
@@ -414,7 +418,32 @@ public class TestAMWebApp {
   }
 
   public static void main(String[] args) {
-    WebApps.$for("yarn", AppContext.class, new MockAppContext(0, 8, 88, 4)).
-        at(58888).inDevMode().start(new AMWebApp()).joinThread();
+    AppContext context = new MockAppContext(0, 8, 88, 4);
+    WebApps.$for("yarn", AppContext.class, context).withResourceConfig(configure(context)).
+        at(58888).inDevMode().start(new AMWebApp(context)).joinThread();
+  }
+
+  protected static ResourceConfig configure(AppContext context) {
+    ResourceConfig config = new ResourceConfig();
+    config.packages("org.apache.hadoop.mapreduce.v2.app.webapp");
+    config.register(new JerseyBinder(context));
+    config.register(AMWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
+
+  private static class JerseyBinder extends AbstractBinder {
+    private AppContext context;
+
+    JerseyBinder(AppContext context) {
+      this.context = context;
+    }
+
+    @Override
+    protected void configure() {
+      bind(context).to(AppContext.class).named("am");
+      bind(new App(context)).to(App.class).named("app");
+    }
   }
 }

+ 118 - 127
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServices.java

@@ -22,11 +22,19 @@ import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.assertResponseS
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
 
 import java.io.StringReader;
 import java.util.Set;
 
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.ServiceUnavailableException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
@@ -37,27 +45,23 @@ import org.apache.hadoop.mapreduce.v2.app.MockAppContext;
 import org.apache.hadoop.util.Sets;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
+
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.api.client.UniformInterfaceException;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import javax.servlet.http.HttpServletResponse;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
 
 /**
  * Test the MapReduce Application master info web services api's. Also test
@@ -68,155 +72,142 @@ import com.sun.jersey.test.framework.WebAppDescriptor;
  */
 public class TestAMWebServices extends JerseyTestBase {
 
-  private static Configuration conf = new Configuration();
+  private static final Configuration CONF = new Configuration();
   private static MockAppContext appContext;
 
-  private static class WebServletModule extends ServletModule {
-    @Override
-    protected void configureServlets() {
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(AMWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature());
+    config.register(JAXBContextResolver.class);
+    return config;
+  }
 
+  private static class JerseyBinder extends AbstractBinder {
+    @Override
+    protected void configure() {
       appContext = new MockAppContext(0, 1, 1, 1);
       appContext.setBlacklistedNodes(Sets.newHashSet("badnode1", "badnode2"));
-
-      bind(JAXBContextResolver.class);
-      bind(AMWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(AppContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-
-      serve("/*").with(GuiceContainer.class);
+      App app = new App(appContext);
+      bind(appContext).to(AppContext.class).named("am");
+      bind(app).to(App.class).named("app");
+      bind(CONF).to(Configuration.class).named("conf");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      bind(response).to(HttpServletResponse.class);
     }
   }
 
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  public TestAMWebServices() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.app.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
-  }
-
   @Test
   public void testAM() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     verifyAMInfo(json.getJSONObject("info"), appContext);
   }
 
   @Test
   public void testAMSlash() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce/")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce/")
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     verifyAMInfo(json.getJSONObject("info"), appContext);
   }
 
   @Test
   public void testAMDefault() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce/")
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce/").request()
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     verifyAMInfo(json.getJSONObject("info"), appContext);
   }
 
   @Test
   public void testAMXML() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    String xml = response.getEntity(String.class);
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .request(MediaType.APPLICATION_XML).get(Response.class);
+    assertEquals(MediaType.APPLICATION_XML + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    String xml = response.readEntity(String.class);
     verifyAMInfoXML(xml, appContext);
   }
 
   @Test
   public void testInfo() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("info").accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("info").request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     verifyAMInfo(json.getJSONObject("info"), appContext);
   }
 
   @Test
   public void testInfoSlash() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("info/").accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("info/").request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     verifyAMInfo(json.getJSONObject("info"), appContext);
   }
 
   @Test
   public void testInfoDefault() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("info/").get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("info/").request().get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     verifyAMInfo(json.getJSONObject("info"), appContext);
   }
 
   @Test
-  public void testInfoXML() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("info/").accept(MediaType.APPLICATION_XML)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    String xml = response.getEntity(String.class);
+  public void testInfoXML() throws Exception {
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("info/").request(MediaType.APPLICATION_XML)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_XML + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    String xml = response.readEntity(String.class);
     verifyAMInfoXML(xml, appContext);
   }
 
   @Test
   public void testInvalidUri() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     String responseStr = "";
     try {
       responseStr = r.path("ws").path("v1").path("mapreduce").path("bogus")
-          .accept(MediaType.APPLICATION_JSON).get(String.class);
+          .request(MediaType.APPLICATION_JSON).get(String.class);
       fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
+    } catch (NotFoundException ne) {
+      Response response = ne.getResponse();
+      assertResponseStatusCode(NOT_FOUND, response.getStatusInfo());
       WebServicesTestUtils.checkStringMatch(
           "error string exists and shouldn't", "", responseStr);
     }
@@ -224,15 +215,15 @@ public class TestAMWebServices extends JerseyTestBase {
 
   @Test
   public void testInvalidUri2() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     String responseStr = "";
     try {
       responseStr = r.path("ws").path("v1").path("invalid")
-          .accept(MediaType.APPLICATION_JSON).get(String.class);
+          .request(MediaType.APPLICATION_JSON).get(String.class);
       fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
+    } catch (NotFoundException ne) {
+      Response response = ne.getResponse();
+      assertResponseStatusCode(NOT_FOUND, response.getStatusInfo());
       WebServicesTestUtils.checkStringMatch(
           "error string exists and shouldn't", "", responseStr);
     }
@@ -240,16 +231,15 @@ public class TestAMWebServices extends JerseyTestBase {
 
   @Test
   public void testInvalidAccept() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     String responseStr = "";
     try {
       responseStr = r.path("ws").path("v1").path("mapreduce")
-          .accept(MediaType.TEXT_PLAIN).get(String.class);
+          .request(MediaType.TEXT_PLAIN).get(String.class);
       fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.INTERNAL_SERVER_ERROR,
-          response.getStatusInfo());
+    } catch (ServiceUnavailableException sue) {
+      Response response = sue.getResponse();
+      assertResponseStatusCode(SERVICE_UNAVAILABLE, response.getStatusInfo());
       WebServicesTestUtils.checkStringMatch(
           "error string exists and shouldn't", "", responseStr);
     }
@@ -257,26 +247,26 @@ public class TestAMWebServices extends JerseyTestBase {
   
   @Test
   public void testBlacklistedNodes() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("blacklistednodes").accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("blacklistednodes").request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     verifyBlacklistedNodesInfo(json, appContext);
   }
   
   @Test
   public void testBlacklistedNodesXML() throws Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("blacklistednodes").accept(MediaType.APPLICATION_XML)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    String xml = response.getEntity(String.class);
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("blacklistednodes").request(MediaType.APPLICATION_XML)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_XML + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    String xml = response.readEntity(String.class);
     verifyBlacklistedNodesInfoXML(xml, appContext);
   }
 
@@ -326,8 +316,9 @@ public class TestAMWebServices extends JerseyTestBase {
   }
   
   public void verifyBlacklistedNodesInfo(JSONObject blacklist, AppContext ctx)
-    throws JSONException, Exception{
-    JSONArray array = blacklist.getJSONArray("blacklistedNodes");
+      throws Exception {
+    JSONObject blacklistednodesinfo = blacklist.getJSONObject("blacklistednodesinfo");
+    JSONArray array = blacklistednodesinfo.getJSONArray("blacklistedNodes");
     assertEquals(array.length(), ctx.getBlacklistedNodes().size());
     for (int i = 0; i < array.length(); i++) {
       assertTrue(ctx.getBlacklistedNodes().contains(array.getString(i)));

+ 73 - 72
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesAttempt.java

@@ -19,15 +19,23 @@
 package org.apache.hadoop.mapreduce.v2.app.webapp;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import java.io.StringReader;
 import java.util.Enumeration;
 import java.util.Map;
 import java.util.Properties;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
@@ -46,24 +54,19 @@ import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
 import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.Singleton;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import javax.inject.Singleton;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 
 /**
  * Test the app master web service Rest API for getting task attempts, a
@@ -73,25 +76,37 @@ import com.sun.jersey.test.framework.WebAppDescriptor;
  */
 public class TestAMWebServicesAttempt extends JerseyTestBase {
 
-  private static Configuration conf = new Configuration();
+  private final static Configuration CONF = new Configuration();
   private static AppContext appContext;
-  private String webserviceUserName = "testuser";
+  private final static String WEB_SERVICE_USER_NAME = "testuser";
 
-  private static class WebServletModule extends ServletModule {
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(AMWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature());
+    config.register(JAXBContextResolver.class);
+    config.register(new TestRMCustomAuthFilter());
+    return config;
+  }
 
+  private static class JerseyBinder extends AbstractBinder {
     @Override
-    protected void configureServlets() {
-      appContext = new MockAppContext(0, 1, 2, 1);
-      bind(JAXBContextResolver.class);
-      bind(AMWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(AppContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-
-      serve("/*").with(GuiceContainer.class);
-      filter("/*").through(TestRMCustomAuthFilter.class);
+    protected void configure() {
+      appContext = new MockAppContext(0, 1, 1, 1);
+      App app = new App(appContext);
+      bind(appContext).to(AppContext.class).named("am");
+      bind(app).to(App.class).named("app");
+      bind(CONF).to(Configuration.class).named("conf");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      when(request.getRemoteUser()).thenReturn(WEB_SERVICE_USER_NAME);
+      bind(response).to(HttpServletResponse.class);
+      bind(request).to(HttpServletRequest.class);
     }
-  };
+  }
 
   @Singleton
   public static class TestRMCustomAuthFilter extends AuthenticationFilter {
@@ -113,30 +128,17 @@ public class TestAMWebServicesAttempt extends JerseyTestBase {
     }
   }
 
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
   @Override
   public void setUp() throws Exception {
     super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
   }
 
   public TestAMWebServicesAttempt() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.app.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
   }
 
   @Test
   public void testGetTaskAttemptIdState() throws Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -149,16 +151,17 @@ public class TestAMWebServicesAttempt extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
               .path("attempts").path(attid).path("state")
-              .queryParam("user.name", webserviceUserName)
-              .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .queryParam("user.name", WEB_SERVICE_USER_NAME)
+              .request(MediaType.APPLICATION_JSON).get(Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
+          JSONObject jobState = json.getJSONObject("jobTaskAttemptState");
           assertEquals("incorrect number of elements", 1, json.length());
-          assertEquals(att.getState().toString(), json.get("state"));
+          assertEquals(att.getState().toString(), jobState.get("state"));
         }
       }
     }
@@ -166,7 +169,7 @@ public class TestAMWebServicesAttempt extends JerseyTestBase {
 
   @Test
   public void testGetTaskAttemptIdXMLState() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
@@ -177,15 +180,15 @@ public class TestAMWebServicesAttempt extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
               .path("attempts").path(attid).path("state")
-              .queryParam("user.name", webserviceUserName)
-              .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+              .queryParam("user.name", WEB_SERVICE_USER_NAME)
+              .request(MediaType.APPLICATION_XML).get(Response.class);
 
-          assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-              response.getType().toString());
-          String xml = response.getEntity(String.class);
+          assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+              response.getMediaType().toString());
+          String xml = response.readEntity(String.class);
           DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
           DocumentBuilder db = dbf.newDocumentBuilder();
           InputSource is = new InputSource();
@@ -203,7 +206,7 @@ public class TestAMWebServicesAttempt extends JerseyTestBase {
 
   @Test
   public void testPutTaskAttemptIdState() throws Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -216,18 +219,18 @@ public class TestAMWebServicesAttempt extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
               .path("attempts").path(attid).path("state")
-              .queryParam("user.name", webserviceUserName)
-              .accept(MediaType.APPLICATION_JSON)
-              .type(MediaType.APPLICATION_JSON)
-              .put(ClientResponse.class, "{\"state\":\"KILLED\"}");
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .queryParam("user.name", WEB_SERVICE_USER_NAME)
+              .request(MediaType.APPLICATION_JSON)
+              .put(Entity.json("{\"jobTaskAttemptState\":{\"state\":\"KILLED\"}}"), Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
+          JSONObject jobState = json.getJSONObject("jobTaskAttemptState");
           assertEquals("incorrect number of elements", 1, json.length());
-          assertEquals(TaskAttemptState.KILLED.toString(), json.get("state"));
+          assertEquals(TaskAttemptState.KILLED.toString(), jobState.get("state"));
         }
       }
     }
@@ -235,7 +238,7 @@ public class TestAMWebServicesAttempt extends JerseyTestBase {
 
   @Test
   public void testPutTaskAttemptIdXMLState() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -248,18 +251,16 @@ public class TestAMWebServicesAttempt extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
               .path("attempts").path(attid).path("state")
-              .queryParam("user.name", webserviceUserName)
-              .accept(MediaType.APPLICATION_XML_TYPE)
-              .type(MediaType.APPLICATION_XML_TYPE)
-              .put(ClientResponse.class,
-                  "<jobTaskAttemptState><state>KILLED" +
-                      "</state></jobTaskAttemptState>");
-          assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-              response.getType().toString());
-          String xml = response.getEntity(String.class);
+              .queryParam("user.name", WEB_SERVICE_USER_NAME)
+              .request(MediaType.APPLICATION_XML_TYPE)
+              .put(Entity.xml("<jobTaskAttemptState><state>KILLED" +
+                      "</state></jobTaskAttemptState>"));
+          assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+              response.getMediaType().toString());
+          String xml = response.readEntity(String.class);
           DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
           DocumentBuilder db = dbf.newDocumentBuilder();
           InputSource is = new InputSource();

+ 120 - 126
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesAttempts.java

@@ -24,12 +24,20 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
 
 import java.io.StringReader;
 import java.util.List;
 import java.util.Map;
 
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.NotFoundException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
@@ -46,27 +54,20 @@ import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt;
 import org.apache.hadoop.mapreduce.v2.util.MRApps;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.api.client.UniformInterfaceException;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 
 /**
  * Test the app master web service Rest API for getting task attempts, a
@@ -81,57 +82,47 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
   private static Configuration conf = new Configuration();
   private static AppContext appContext;
 
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(AMWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature());
+    config.register(JAXBContextResolver.class);
+    return config;
+  }
 
-  private static class WebServletModule extends ServletModule {
+  private static class JerseyBinder extends AbstractBinder {
     @Override
-    protected void configureServlets() {
+    protected void configure() {
       appContext = new MockAppContext(0, 1, 2, 1);
-      bind(JAXBContextResolver.class);
-      bind(AMWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(AppContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-
-      serve("/*").with(GuiceContainer.class);
+      App app = new App(appContext);
+      bind(appContext).to(AppContext.class).named("am");
+      bind(app).to(App.class).named("app");
+      bind(conf).to(Configuration.class).named("conf");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(response).to(HttpServletResponse.class);
+      bind(request).to(HttpServletRequest.class);
     }
   }
 
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  public TestAMWebServicesAttempts() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.app.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
-  }
-
   @Test
   public void testTaskAttempts() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid).path("attempts")
-            .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON).get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         verifyAMTaskAttempts(json, task);
       }
     }
@@ -139,19 +130,19 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptsSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid).path("attempts/")
-            .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON).get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         verifyAMTaskAttempts(json, task);
       }
     }
@@ -159,19 +150,19 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptsDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid).path("attempts")
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON).get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         verifyAMTaskAttempts(json, task);
       }
     }
@@ -179,20 +170,20 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptsXML() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid).path("attempts")
-            .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+            .request(MediaType.APPLICATION_XML).get(Response.class);
 
-        assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        String xml = response.getEntity(String.class);
+        assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        String xml = response.readEntity(String.class);
         DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
         DocumentBuilder db = dbf.newDocumentBuilder();
         InputSource is = new InputSource();
@@ -209,7 +200,7 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptId() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -222,13 +213,13 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
-              .path("attempts").path(attid).accept(MediaType.APPLICATION_JSON)
-              .get(ClientResponse.class);
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .path("attempts").path(attid).request(MediaType.APPLICATION_JSON)
+              .get(Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
           assertEquals("incorrect number of elements", 1, json.length());
           JSONObject info = json.getJSONObject("taskAttempt");
           verifyAMTaskAttempt(info, att, task.getType());
@@ -239,7 +230,7 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptIdSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -252,13 +243,13 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
               .path("attempts").path(attid + "/")
-              .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .request(MediaType.APPLICATION_JSON).get(Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
           assertEquals("incorrect number of elements", 1, json.length());
           JSONObject info = json.getJSONObject("taskAttempt");
           verifyAMTaskAttempt(info, att, task.getType());
@@ -268,8 +259,8 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
   }
 
   @Test
-  public void testTaskAttemptIdDefault() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testTaskAttemptIdDefault() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -282,12 +273,13 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
-              .path("attempts").path(attid).get(ClientResponse.class);
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .path("attempts").path(attid)
+              .request(MediaType.APPLICATION_JSON).get(Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
           assertEquals("incorrect number of elements", 1, json.length());
           JSONObject info = json.getJSONObject("taskAttempt");
           verifyAMTaskAttempt(info, att, task.getType());
@@ -297,8 +289,8 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
   }
 
   @Test
-  public void testTaskAttemptIdXML() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testTaskAttemptIdXML() throws Exception {
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
@@ -309,14 +301,14 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
-              .path("attempts").path(attid).accept(MediaType.APPLICATION_XML)
-              .get(ClientResponse.class);
+              .path("attempts").path(attid).request(MediaType.APPLICATION_XML)
+              .get(Response.class);
 
-          assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-              response.getType().toString());
-          String xml = response.getEntity(String.class);
+          assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+              response.getMediaType().toString());
+          String xml = response.readEntity(String.class);
           DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
           DocumentBuilder db = dbf.newDocumentBuilder();
           InputSource is = new InputSource();
@@ -336,7 +328,7 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
   public void testTaskAttemptIdBogus() throws JSONException, Exception {
 
     testTaskAttemptIdErrorGeneric("bogusid",
-        "java.lang.Exception: TaskAttemptId string : bogusid is not properly formed");
+        "TaskAttemptId string : bogusid is not properly formed");
   }
 
   @Test
@@ -344,33 +336,34 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
 
     testTaskAttemptIdErrorGeneric(
         "attempt_0_12345_m_000000_0",
-        "java.lang.Exception: Error getting info on task attempt id attempt_0_12345_m_000000_0");
+        "Error getting info on task attempt id attempt_0_12345_m_000000_0");
   }
 
   @Test
   public void testTaskAttemptIdInvalid() throws JSONException, Exception {
 
     testTaskAttemptIdErrorGeneric("attempt_0_12345_d_000000_0",
-        "java.lang.Exception: Bad TaskType identifier. TaskAttemptId string : attempt_0_12345_d_000000_0 is not properly formed.");
+        "Bad TaskType identifier. " +
+        "TaskAttemptId string : attempt_0_12345_d_000000_0 is not properly formed.");
   }
 
   @Test
   public void testTaskAttemptIdInvalid2() throws JSONException, Exception {
 
     testTaskAttemptIdErrorGeneric("attempt_12345_m_000000_0",
-        "java.lang.Exception: TaskAttemptId string : attempt_12345_m_000000_0 is not properly formed");
+        "TaskAttemptId string : attempt_12345_m_000000_0 is not properly formed");
   }
 
   @Test
   public void testTaskAttemptIdInvalid3() throws JSONException, Exception {
 
     testTaskAttemptIdErrorGeneric("attempt_0_12345_m_000000",
-        "java.lang.Exception: TaskAttemptId string : attempt_0_12345_m_000000 is not properly formed");
+        "TaskAttemptId string : attempt_0_12345_m_000000 is not properly formed");
   }
 
   private void testTaskAttemptIdErrorGeneric(String attid, String error)
       throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -382,25 +375,24 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
         try {
           r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
               .path("tasks").path(tid).path("attempts").path(attid)
-              .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+              .request(MediaType.APPLICATION_JSON).get(JSONObject.class);
           fail("should have thrown exception on invalid uri");
-        } catch (UniformInterfaceException ue) {
-          ClientResponse response = ue.getResponse();
-          assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject msg = response.getEntity(JSONObject.class);
+        } catch (NotFoundException ue) {
+          Response response = ue.getResponse();
+          assertResponseStatusCode(NOT_FOUND, response.getStatusInfo());
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          String entity = response.readEntity(String.class);
+          JSONObject msg = new JSONObject(entity);
           JSONObject exception = msg.getJSONObject("RemoteException");
           assertEquals("incorrect number of elements", 3, exception.length());
           String message = exception.getString("message");
           String type = exception.getString("exception");
           String classname = exception.getString("javaClassName");
-          WebServicesTestUtils.checkStringMatch("exception message", error,
-              message);
-          WebServicesTestUtils.checkStringMatch("exception type",
-              "NotFoundException", type);
+          WebServicesTestUtils.checkStringMatch("exception message", error, message);
+          WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
           WebServicesTestUtils.checkStringMatch("exception classname",
-              "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
+               "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
         }
       }
     }
@@ -458,11 +450,13 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject attempts = json.getJSONObject("taskAttempts");
     assertEquals("incorrect number of elements", 1, json.length());
-    JSONArray arr = attempts.getJSONArray("taskAttempt");
+    JSONObject taskAttempt = attempts.getJSONObject("taskAttempt");
+    JSONArray arr = new JSONArray();
+    arr.put(taskAttempt);
     for (TaskAttempt att : task.getAttempts().values()) {
       TaskAttemptId id = att.getID();
       String attid = MRApps.toString(id);
-      Boolean found = false;
+      boolean found = false;
 
       for (int i = 0; i < arr.length(); i++) {
         JSONObject info = arr.getJSONObject(i);
@@ -482,7 +476,7 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
     for (TaskAttempt att : task.getAttempts().values()) {
       TaskAttemptId id = att.getID();
       String attid = MRApps.toString(id);
-      Boolean found = false;
+      boolean found = false;
       for (int i = 0; i < nodes.getLength(); i++) {
         Element element = (Element) nodes.item(i);
         assertFalse("task attempt should not contain any attributes, it can lead to incorrect JSON marshaling",
@@ -552,7 +546,7 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptIdCounters() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -565,13 +559,13 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
               .path("attempts").path(attid).path("counters")
-              .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .request(MediaType.APPLICATION_JSON).get(Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
           assertEquals("incorrect number of elements", 1, json.length());
           JSONObject info = json.getJSONObject("jobTaskAttemptCounters");
           verifyAMJobTaskAttemptCounters(info, att);
@@ -581,8 +575,8 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
   }
 
   @Test
-  public void testTaskAttemptIdXMLCounters() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testTaskAttemptIdXMLCounters() throws Exception {
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
@@ -593,14 +587,14 @@ public class TestAMWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+          Response response = r.path("ws").path("v1").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
               .path("attempts").path(attid).path("counters")
-              .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+              .request(MediaType.APPLICATION_XML).get(Response.class);
 
-          assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-              response.getType().toString());
-          String xml = response.getEntity(String.class);
+          assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+              response.getMediaType().toString());
+          String xml = response.readEntity(String.class);
           DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
           DocumentBuilder db = dbf.newDocumentBuilder();
           InputSource is = new InputSource();

+ 58 - 66
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesJobConf.java

@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
 
 import java.io.File;
 import java.io.IOException;
@@ -29,7 +30,12 @@ import java.io.OutputStream;
 import java.io.StringReader;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
@@ -46,27 +52,21 @@ import org.apache.hadoop.mapreduce.v2.app.job.Job;
 import org.apache.hadoop.mapreduce.v2.util.MRApps;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
 import org.junit.AfterClass;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
-
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 /**
  * Test the app master web service Rest API for getting the job conf. This
  * requires created a temporary configuration file.
@@ -81,13 +81,22 @@ public class TestAMWebServicesJobConf extends JerseyTestBase {
   private static File testConfDir = new File("target",
       TestAMWebServicesJobConf.class.getSimpleName() + "confDir");
 
-  private static class WebServletModule extends ServletModule {
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(AMWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(JAXBContextResolver.class);
+    config.register(new JettisonFeature());
+    return config;
+  }
 
+  private static class JerseyBinder extends AbstractBinder {
     @Override
-    protected void configureServlets() {
+    protected void configure() {
 
-      Path confPath = new Path(testConfDir.toString(),
-          MRJobConfig.JOB_CONF_FILE);
+      Path confPath = new Path(testConfDir.toString(), MRJobConfig.JOB_CONF_FILE);
       Configuration config = new Configuration();
 
       FileSystem localFs;
@@ -110,29 +119,21 @@ public class TestAMWebServicesJobConf extends JerseyTestBase {
       }
 
       appContext = new MockAppContext(0, 2, 1, confPath);
-
-      bind(JAXBContextResolver.class);
-      bind(AMWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(AppContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-
-      serve("/*").with(GuiceContainer.class);
+      App app = new App(appContext);
+      bind(appContext).to(AppContext.class).named("am");
+      bind(app).to(App.class).named("app");
+      bind(conf).to(Configuration.class).named("conf");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(response).to(HttpServletResponse.class);
+      bind(request).to(HttpServletRequest.class);
     }
-  };
-
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
   }
 
-  @Before
   @Override
   public void setUp() throws Exception {
     super.setUp();
     testConfDir.mkdir();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
   }
 
   @AfterClass
@@ -140,27 +141,19 @@ public class TestAMWebServicesJobConf extends JerseyTestBase {
     FileUtil.fullyDelete(testConfDir);
   }
 
-  public TestAMWebServicesJobConf() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.app.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
-  }
-
   @Test
-  public void testJobConf() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobConf() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("conf")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("conf");
       verifyAMJobConf(info, jobsMap.get(id));
@@ -168,18 +161,17 @@ public class TestAMWebServicesJobConf extends JerseyTestBase {
   }
 
   @Test
-  public void testJobConfSlash() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobConfSlash() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("conf/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("conf");
       verifyAMJobConf(info, jobsMap.get(id));
@@ -187,17 +179,17 @@ public class TestAMWebServicesJobConf extends JerseyTestBase {
   }
 
   @Test
-  public void testJobConfDefault() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobConfDefault() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-          .path("jobs").path(jobId).path("conf").get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("mapreduce")
+          .path("jobs").path(jobId).path("conf").request().get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("conf");
       verifyAMJobConf(info, jobsMap.get(id));
@@ -205,18 +197,18 @@ public class TestAMWebServicesJobConf extends JerseyTestBase {
   }
 
   @Test
-  public void testJobConfXML() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobConfXML() throws Exception {
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("conf")
-          .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+          .request(MediaType.APPLICATION_XML).get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();

+ 213 - 221
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesJobs.java

@@ -24,12 +24,19 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
 
 import java.io.StringReader;
 import java.util.List;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
@@ -48,27 +55,20 @@ import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.api.records.NodeId;
 import org.apache.hadoop.yarn.util.Times;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.api.client.UniformInterfaceException;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 
 /**
  * Test the app master web service Rest API for getting jobs, a specific job,
@@ -84,53 +84,46 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   private static Configuration conf = new Configuration();
   private static AppContext appContext;
 
-  private static class WebServletModule extends ServletModule {
-    @Override
-    protected void configureServlets() {
-      appContext = new MockAppContext(0, 1, 2, 1);
-      bind(JAXBContextResolver.class);
-      bind(AMWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(AppContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-
-      serve("/*").with(GuiceContainer.class);
-    }
-  }
-
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
   @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(AMWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature());
+    config.register(JAXBContextResolver.class);
+    return config;
   }
 
-  public TestAMWebServicesJobs() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.app.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
+  private static class JerseyBinder extends AbstractBinder {
+    @Override
+    protected void configure() {
+      appContext = new MockAppContext(0, 1, 2, 1);
+      App app = new App(appContext);
+      bind(appContext).to(AppContext.class).named("am");
+      bind(app).to(App.class).named("app");
+      bind(conf).to(Configuration.class).named("conf");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(response).to(HttpServletResponse.class);
+      bind(request).to(HttpServletRequest.class);
+    }
   }
 
   @Test
-  public void testJobs() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("jobs").accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+  public void testJobs() throws Exception {
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("jobs").request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
-    JSONArray arr = jobs.getJSONArray("job");
+    JSONObject jobObject = jobs.getJSONObject("job");
+    JSONArray arr = new JSONArray();
+    arr.put(jobObject);
     JSONObject info = arr.getJSONObject(0);
     Job job = appContext.getJob(MRApps.toJobID(info.getString("id")));
     verifyAMJob(info, job);
@@ -138,17 +131,19 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobsSlash() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("jobs/").accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+  public void testJobsSlash() throws Exception {
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("jobs/").request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
-    JSONArray arr = jobs.getJSONArray("job");
+    JSONObject jobObject = jobs.getJSONObject("job");
+    JSONArray arr = new JSONArray();
+    arr.put(jobObject);
     JSONObject info = arr.getJSONObject(0);
     Job job = appContext.getJob(MRApps.toJobID(info.getString("id")));
     verifyAMJob(info, job);
@@ -156,16 +151,18 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobsDefault() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("jobs").get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+  public void testJobsDefault() throws Exception {
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("jobs").request().get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
-    JSONArray arr = jobs.getJSONArray("job");
+    JSONObject jobObject = jobs.getJSONObject("job");
+    JSONArray arr = new JSONArray();
+    arr.put(jobObject);
     JSONObject info = arr.getJSONObject(0);
     Job job = appContext.getJob(MRApps.toJobID(info.getString("id")));
     verifyAMJob(info, job);
@@ -174,13 +171,13 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobsXML() throws Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-        .path("jobs").accept(MediaType.APPLICATION_XML)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    String xml = response.getEntity(String.class);
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1").path("mapreduce")
+        .path("jobs").request(MediaType.APPLICATION_XML)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    String xml = response.readEntity(String.class);
     DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
     DocumentBuilder db = dbf.newDocumentBuilder();
     InputSource is = new InputSource();
@@ -195,18 +192,18 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobId() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobId() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-          .path("jobs").path(jobId).accept(MediaType.APPLICATION_JSON)
-          .get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("mapreduce")
+          .path("jobs").path(jobId).request(MediaType.APPLICATION_JSON)
+          .get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("job");
       verifyAMJob(info, jobsMap.get(id));
@@ -215,18 +212,18 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobIdSlash() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobIdSlash() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-          .path("jobs").path(jobId + "/").accept(MediaType.APPLICATION_JSON)
-          .get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("mapreduce")
+          .path("jobs").path(jobId + "/").request(MediaType.APPLICATION_JSON)
+          .get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("job");
       verifyAMJob(info, jobsMap.get(id));
@@ -234,17 +231,17 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobIdDefault() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobIdDefault() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-          .path("jobs").path(jobId).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("mapreduce")
+          .path("jobs").path(jobId).request().get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("job");
       verifyAMJob(info, jobsMap.get(id));
@@ -253,26 +250,26 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobIdNonExist() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobIdNonExist() throws Exception {
+    WebTarget r = targetWithJsonObject();
 
     try {
-      r.path("ws").path("v1").path("mapreduce").path("jobs")
-          .path("job_0_1234").get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject msg = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("mapreduce").path("jobs")
+          .path("job_0_1234").request().get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject msg = response.readEntity(JSONObject.class);
       JSONObject exception = msg.getJSONObject("RemoteException");
       assertEquals("incorrect number of elements", 3, exception.length());
       String message = exception.getString("message");
       String type = exception.getString("exception");
       String classname = exception.getString("javaClassName");
       WebServicesTestUtils.checkStringMatch("exception message",
-          "java.lang.Exception: job, job_0_1234, is not found", message);
+          "job, job_0_1234, is not found", message);
       WebServicesTestUtils.checkStringMatch("exception type",
           "NotFoundException", type);
       WebServicesTestUtils.checkStringMatch("exception classname",
@@ -281,19 +278,19 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobIdInvalid() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobIdInvalid() throws Exception {
+    WebTarget r = targetWithJsonObject();
 
     try {
-      r.path("ws").path("v1").path("mapreduce").path("jobs").path("job_foo")
-          .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject msg = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("mapreduce").path("jobs").path("job_foo")
+          .request(MediaType.APPLICATION_JSON).get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject msg = response.readEntity(JSONObject.class);
       JSONObject exception = msg.getJSONObject("RemoteException");
       assertEquals("incorrect number of elements", 3, exception.length());
       String message = exception.getString("message");
@@ -305,19 +302,19 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
 
   // verify the exception output default is JSON
   @Test
-  public void testJobIdInvalidDefault() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobIdInvalidDefault() throws Exception {
+    WebTarget r = targetWithJsonObject();
 
     try {
-      r.path("ws").path("v1").path("mapreduce").path("jobs").path("job_foo")
-          .get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject msg = response.getEntity(JSONObject.class);
+      Response response =
+          r.path("ws").path("v1").path("mapreduce").path("jobs").path("job_foo").request().get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject msg = response.readEntity(JSONObject.class);
       JSONObject exception = msg.getJSONObject("RemoteException");
       assertEquals("incorrect number of elements", 3, exception.length());
       String message = exception.getString("message");
@@ -330,18 +327,18 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   // test that the exception output works in XML
   @Test
   public void testJobIdInvalidXML() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
 
     try {
-      r.path("ws").path("v1").path("mapreduce").path("jobs").path("job_foo")
-          .accept(MediaType.APPLICATION_XML).get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String msg = response.getEntity(String.class);
+      Response response = r.path("ws").path("v1").path("mapreduce").path("jobs").path("job_foo")
+          .request(MediaType.APPLICATION_XML).get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String msg = response.readEntity(String.class);
       System.out.println(msg);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
@@ -352,15 +349,14 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
       Element element = (Element) nodes.item(0);
       String message = WebServicesTestUtils.getXmlString(element, "message");
       String type = WebServicesTestUtils.getXmlString(element, "exception");
-      String classname = WebServicesTestUtils.getXmlString(element,
-          "javaClassName");
+      String classname = WebServicesTestUtils.getXmlString(element, "javaClassName");
       verifyJobIdInvalid(message, type, classname);
     }
   }
 
   private void verifyJobIdInvalid(String message, String type, String classname) {
     WebServicesTestUtils.checkStringMatch("exception message",
-        "java.lang.Exception: JobId string : job_foo is not properly formed",
+        "JobId string : job_foo is not properly formed",
         message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "NotFoundException", type);
@@ -370,30 +366,28 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobIdInvalidBogus() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
 
     try {
-      r.path("ws").path("v1").path("mapreduce").path("jobs").path("bogusfoo")
-          .get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject msg = response.getEntity(JSONObject.class);
+      Response response =
+          r.path("ws").path("v1").path("mapreduce").path("jobs").path("bogusfoo").request().get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject msg = response.readEntity(JSONObject.class);
       JSONObject exception = msg.getJSONObject("RemoteException");
       assertEquals("incorrect number of elements", 3, exception.length());
       String message = exception.getString("message");
       String type = exception.getString("exception");
       String classname = exception.getString("javaClassName");
-      WebServicesTestUtils
-          .checkStringMatch(
-              "exception message",
-              "java.lang.Exception: JobId string : bogusfoo is not properly formed",
-              message);
-      WebServicesTestUtils.checkStringMatch("exception type",
-          "NotFoundException", type);
+      WebServicesTestUtils.checkStringMatch(
+          "exception message",
+          "JobId string : bogusfoo is not properly formed",
+          message);
+      WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
       WebServicesTestUtils.checkStringMatch("exception classname",
           "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
     }
@@ -401,17 +395,17 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobIdXML() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-          .path("jobs").path(jobId).accept(MediaType.APPLICATION_XML)
-          .get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+      Response response = r.path("ws").path("v1").path("mapreduce")
+          .path("jobs").path(jobId).request(MediaType.APPLICATION_XML)
+          .get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();
@@ -635,18 +629,17 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobCounters() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobCounters() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("counters")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobCounters");
       verifyAMJobCounters(info, jobsMap.get(id));
@@ -654,18 +647,18 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobCountersSlash() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobCountersSlash() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("counters/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobCounters");
       verifyAMJobCounters(info, jobsMap.get(id));
@@ -674,16 +667,16 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobCountersDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-          .path("jobs").path(jobId).path("counters/").get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("mapreduce")
+          .path("jobs").path(jobId).path("counters/").request().get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobCounters");
       verifyAMJobCounters(info, jobsMap.get(id));
@@ -692,17 +685,17 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobCountersXML() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("counters")
-          .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+          .request(MediaType.APPLICATION_XML).get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();
@@ -792,17 +785,17 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobAttempts() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1")
+      Response response = r.path("ws").path("v1")
           .path("mapreduce").path("jobs").path(jobId).path("jobattempts")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobAttempts");
       verifyJobAttempts(info, jobsMap.get(id));
@@ -811,17 +804,16 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobAttemptsSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1")
+      Response response = r.path("ws").path("v1")
           .path("mapreduce").path("jobs").path(jobId).path("jobattempts/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobAttempts");
       verifyJobAttempts(info, jobsMap.get(id));
@@ -829,18 +821,18 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobAttemptsDefault() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobAttemptsDefault() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1")
-          .path("mapreduce").path("jobs").path(jobId).path("jobattempts")
-          .get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1")
+          .path("mapreduce").path("jobs").path(jobId).path("jobattempts").request()
+          .get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobAttempts");
       verifyJobAttempts(info, jobsMap.get(id));
@@ -849,17 +841,17 @@ public class TestAMWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobAttemptsXML() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1")
+      Response response = r.path("ws").path("v1")
           .path("mapreduce").path("jobs").path(jobId).path("jobattempts")
-          .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+          .request(MediaType.APPLICATION_XML).get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();

+ 211 - 216
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesTasks.java

@@ -22,12 +22,19 @@ import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.assertResponseS
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
 
 import java.io.StringReader;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
@@ -44,27 +51,20 @@ import org.apache.hadoop.mapreduce.v2.app.job.Task;
 import org.apache.hadoop.mapreduce.v2.util.MRApps;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.api.client.UniformInterfaceException;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 
 /**
  * Test the app master web service Rest API for getting tasks, a specific task,
@@ -76,57 +76,49 @@ import com.sun.jersey.test.framework.WebAppDescriptor;
  */
 public class TestAMWebServicesTasks extends JerseyTestBase {
 
-  private static Configuration conf = new Configuration();
+  private static final Configuration CONF = new Configuration();
   private static AppContext appContext;
 
-  private static class WebServletModule extends ServletModule {
-    @Override
-    protected void configureServlets() {
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(AMWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
 
+  private static class JerseyBinder extends AbstractBinder {
+    @Override
+    protected void configure() {
       appContext = new MockAppContext(0, 1, 2, 1);
-      bind(JAXBContextResolver.class);
-      bind(AMWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(AppContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-
-      serve("/*").with(GuiceContainer.class);
+      App app = new App(appContext);
+      bind(appContext).to(AppContext.class).named("am");
+      bind(app).to(App.class).named("app");
+      bind(CONF).to(Configuration.class).named("conf");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(response).to(HttpServletResponse.class);
+      bind(request).to(HttpServletRequest.class);
     }
   }
 
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
   public TestAMWebServicesTasks() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.app.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
   }
 
   @Test
   public void testTasks() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("tasks")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
       JSONArray arr = tasks.getJSONArray("task");
@@ -138,15 +130,15 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-          .path("jobs").path(jobId).path("tasks").get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("mapreduce")
+          .path("jobs").path(jobId).path("tasks").request().get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
       JSONArray arr = tasks.getJSONArray("task");
@@ -158,16 +150,16 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("tasks/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
       JSONArray arr = tasks.getJSONArray("task");
@@ -180,16 +172,16 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
   @Test
   public void testTasksXML() throws JSONException, Exception {
 
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("tasks")
-          .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+          .request(MediaType.APPLICATION_XML).get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();
@@ -204,20 +196,22 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksQueryMap() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String type = "m";
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("tasks").queryParam("type", type)
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
-      JSONArray arr = tasks.getJSONArray("task");
+      JSONObject task = tasks.getJSONObject("task");
+      JSONArray arr = new JSONArray();
+      arr.put(task);
       assertEquals("incorrect number of elements", 1, arr.length());
       verifyAMTask(arr, jobsMap.get(id), type);
     }
@@ -225,20 +219,22 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksQueryReduce() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String type = "r";
-      ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("mapreduce")
           .path("jobs").path(jobId).path("tasks").queryParam("type", type)
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
-      JSONArray arr = tasks.getJSONArray("task");
+      JSONObject task = tasks.getJSONObject("task");
+      JSONArray arr = new JSONArray();
+      arr.put(task);
       assertEquals("incorrect number of elements", 1, arr.length());
       verifyAMTask(arr, jobsMap.get(id), type);
     }
@@ -246,7 +242,7 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksQueryInvalid() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
@@ -254,23 +250,23 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
       String tasktype = "reduce";
 
       try {
-        r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
+        Response response = r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
             .path("tasks").queryParam("type", tasktype)
-            .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON).get();
+        throw new BadRequestException(response);
+      } catch (BadRequestException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringMatch("exception message",
-            "java.lang.Exception: tasktype must be either m or r", message);
+            "tasktype must be either m or r", message);
         WebServicesTestUtils.checkStringMatch("exception type",
             "BadRequestException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
@@ -281,19 +277,19 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskId() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid)
-            .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON).get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("task");
         verifyAMSingleTask(info, task);
@@ -303,19 +299,19 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid + "/")
-            .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON).get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("task");
         verifyAMSingleTask(info, task);
@@ -325,19 +321,19 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-            .path("jobs").path(jobId).path("tasks").path(tid)
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("mapreduce")
+            .path("jobs").path(jobId).path("tasks").path(tid).request()
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("task");
         verifyAMSingleTask(info, task);
@@ -347,31 +343,32 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdBogus() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "bogustaskid";
       try {
-        r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
-            .path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
+            .path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
+            .path("tasks").path(tid).request().get();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringEqual("exception message",
-            "java.lang.Exception: TaskId string : "
-                + "bogustaskid is not properly formed"
-                + "\nReason: java.util.regex.Matcher[pattern=" +
-                TaskID.TASK_ID_REGEX + " region=0,11 lastmatch=]", message);
+            "TaskId string : " +
+            "bogustaskid is not properly formed"
+            + "\nReason: java.util.regex.Matcher[pattern=" +
+            TaskID.TASK_ID_REGEX + " region=0,11 lastmatch=]", message);
         WebServicesTestUtils.checkStringMatch("exception type",
             "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
@@ -382,31 +379,30 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdNonExist() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "task_0_0000_m_000000";
       try {
-        r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
-            .path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
+            .path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        String entity = response.readEntity(String.class);
+        JSONObject msg = new JSONObject(entity);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringMatch("exception message",
-            "java.lang.Exception: task not found with id task_0_0000_m_000000",
-            message);
-        WebServicesTestUtils.checkStringMatch("exception type",
-            "NotFoundException", type);
+            "task not found with id task_0_0000_m_000000", message);
+        WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
             "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
       }
@@ -415,31 +411,31 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdInvalid() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "task_0_0000_d_000000";
       try {
-        r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
-            .path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
+            .path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringEqual("exception message",
-            "java.lang.Exception: TaskId string : "
-                + "task_0_0000_d_000000 is not properly formed"
-                + "\nReason: java.util.regex.Matcher[pattern=" +
-                TaskID.TASK_ID_REGEX + " region=0,20 lastmatch=]", message);
+            "TaskId string : "
+            + "task_0_0000_d_000000 is not properly formed"
+            + "\nReason: java.util.regex.Matcher[pattern=" +
+            TaskID.TASK_ID_REGEX + " region=0,20 lastmatch=]", message);
         WebServicesTestUtils.checkStringMatch("exception type",
             "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
@@ -450,33 +446,32 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdInvalid2() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "task_0_m_000000";
       try {
-        r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
-            .path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
+            .path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringEqual("exception message",
-            "java.lang.Exception: TaskId string : "
-                + "task_0_m_000000 is not properly formed"
-                + "\nReason: java.util.regex.Matcher[pattern=" +
-                TaskID.TASK_ID_REGEX + " region=0,15 lastmatch=]", message);
-        WebServicesTestUtils.checkStringMatch("exception type",
-            "NotFoundException", type);
+            "TaskId string : "
+             + "task_0_m_000000 is not properly formed"
+             + "\nReason: java.util.regex.Matcher[pattern=" +
+             TaskID.TASK_ID_REGEX + " region=0,15 lastmatch=]", message);
+        WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
             "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
       }
@@ -485,55 +480,55 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdInvalid3() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "task_0_0000_m";
       try {
-        r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
-            .path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("mapreduce").path("jobs").path(jobId)
+            .path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringEqual("exception message",
-            "java.lang.Exception: TaskId string : "
-                + "task_0_0000_m is not properly formed"
-                + "\nReason: java.util.regex.Matcher[pattern=" +
-                TaskID.TASK_ID_REGEX + " region=0,13 lastmatch=]", message);
+            "TaskId string : "
+             + "task_0_0000_m is not properly formed"
+             + "\nReason: java.util.regex.Matcher[pattern=" +
+             TaskID.TASK_ID_REGEX + " region=0,13 lastmatch=]", message);
         WebServicesTestUtils.checkStringMatch("exception type",
-            "NotFoundException", type);
+             "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
-            "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
+             "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
       }
     }
   }
 
   @Test
-  public void testTaskIdXML() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testTaskIdXML() throws Exception {
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid)
-            .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+            .request(MediaType.APPLICATION_XML).get(Response.class);
 
-        assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        String xml = response.getEntity(String.class);
+        assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        String xml = response.readEntity(String.class);
         DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
         DocumentBuilder db = dbf.newDocumentBuilder();
         InputSource is = new InputSource();
@@ -564,7 +559,7 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
     for (Task task : job.getTasks().values()) {
       TaskId id = task.getID();
       String tid = MRApps.toString(id);
-      Boolean found = false;
+      boolean found = false;
       if (type != null && task.getType() == MRApps.taskType(type)) {
 
         for (int i = 0; i < arr.length(); i++) {
@@ -620,7 +615,7 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
     for (Task task : job.getTasks().values()) {
       TaskId id = task.getID();
       String tid = MRApps.toString(id);
-      Boolean found = false;
+      boolean found = false;
       for (int i = 0; i < nodes.getLength(); i++) {
         Element element = (Element) nodes.item(i);
 
@@ -635,19 +630,19 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdCounters() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid).path("counters")
-            .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON).get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("jobTaskCounters");
         verifyAMJobTaskCounters(info, task);
@@ -657,19 +652,19 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdCountersSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid).path("counters/")
-            .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON).get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("jobTaskCounters");
         verifyAMJobTaskCounters(info, task);
@@ -679,19 +674,19 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdCountersDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
-            .path("jobs").path(jobId).path("tasks").path(tid).path("counters")
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("mapreduce")
+            .path("jobs").path(jobId).path("tasks").path(tid).path("counters").request()
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("jobTaskCounters");
         verifyAMJobTaskCounters(info, task);
@@ -701,19 +696,19 @@ public class TestAMWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testJobTaskCountersXML() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("mapreduce")
+        Response response = r.path("ws").path("v1").path("mapreduce")
             .path("jobs").path(jobId).path("tasks").path(tid).path("counters")
-            .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        String xml = response.getEntity(String.class);
+            .request(MediaType.APPLICATION_XML).get(Response.class);
+        assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        String xml = response.readEntity(String.class);
         DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
         DocumentBuilder db = dbf.newDocumentBuilder();
         InputSource is = new InputSource();

+ 5 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-common/pom.xml

@@ -61,6 +61,11 @@
       <artifactId>junit-jupiter-engine</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.junit.platform</groupId>
       <artifactId>junit-platform-launcher</artifactId>

+ 20 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/pom.xml

@@ -72,6 +72,26 @@
       <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 30 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/pom.xml

@@ -85,6 +85,36 @@
       <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.media</groupId>
+      <artifactId>jersey-media-json-jettison</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>jakarta.ws.rs</groupId>
+      <artifactId>jakarta.ws.rs-api</artifactId>
+      <scope>compile</scope>
+    </dependency>
+      <dependency>
+          <groupId>org.junit.jupiter</groupId>
+          <artifactId>junit-jupiter-api</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.junit.jupiter</groupId>
+          <artifactId>junit-jupiter-engine</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.junit.jupiter</groupId>
+          <artifactId>junit-jupiter-params</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.junit.platform</groupId>
+          <artifactId>junit-platform-launcher</artifactId>
+          <scope>test</scope>
+      </dependency>
   </dependencies>
 
   <build>

+ 38 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java

@@ -72,6 +72,8 @@ import org.apache.hadoop.mapreduce.v2.app.job.Job;
 import org.apache.hadoop.mapreduce.v2.app.job.Task;
 import org.apache.hadoop.mapreduce.v2.app.security.authorize.ClientHSPolicyProvider;
 import org.apache.hadoop.mapreduce.v2.hs.webapp.HsWebApp;
+import org.apache.hadoop.mapreduce.v2.hs.webapp.HsWebServices;
+import org.apache.hadoop.mapreduce.v2.hs.webapp.JAXBContextResolver;
 import org.apache.hadoop.mapreduce.v2.jobhistory.JHAdminConfig;
 import org.apache.hadoop.mapreduce.v2.util.MRWebAppUtil;
 import org.apache.hadoop.net.NetUtils;
@@ -86,10 +88,14 @@ import org.apache.hadoop.yarn.factories.RecordFactory;
 import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
 import org.apache.hadoop.yarn.ipc.YarnRPC;
 import org.apache.hadoop.yarn.util.Records;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
 import org.apache.hadoop.yarn.webapp.WebApp;
 import org.apache.hadoop.yarn.webapp.WebApps;
 
 import org.apache.hadoop.classification.VisibleForTesting;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -171,6 +177,7 @@ public class HistoryClientService extends AbstractService {
         .withCSRFProtection(JHAdminConfig.MR_HISTORY_CSRF_PREFIX)
         .withXFSProtection(JHAdminConfig.MR_HISTORY_XFS_PREFIX)
         .withAppClientProtocol(appClientProtocol)
+        .withResourceConfig(configure(conf, appClientProtocol))
         .at(NetUtils.getHostPortString(bindAddress)).start(webApp);
     
     String connectHost = MRWebAppUtil.getJHSWebappURLWithoutScheme(conf).split(":")[0];
@@ -460,4 +467,35 @@ public class HistoryClientService extends AbstractService {
     }
 
   }
+
+  protected ResourceConfig configure(Configuration configuration,
+      ApplicationClientProtocol protocol) {
+    ResourceConfig config = new ResourceConfig();
+    config.packages("org.apache.hadoop.mapreduce.v2.hs.webapp");
+    config.register(new HSJerseyBinder(configuration, protocol));
+    config.register(HsWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
+
+  private class HSJerseyBinder extends AbstractBinder {
+
+    private Configuration configuration;
+    private ApplicationClientProtocol protocol;
+
+    HSJerseyBinder(Configuration pConfiguration,
+        ApplicationClientProtocol acProtocol) {
+      this.configuration = pConfiguration;
+      this.protocol = acProtocol;
+    }
+
+    @Override
+    protected void configure() {
+      bind(history).to(HistoryContext.class).named("ctx");
+      bind(configuration).to(Configuration.class).named("conf");
+      bind(webApp).to(WebApp.class).named("hsWebApp");
+      bind(protocol).to(ApplicationClientProtocol.class).named("appClient");
+    }
+  }
 }

+ 0 - 4
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsWebApp.java

@@ -28,7 +28,6 @@ import static org.apache.hadoop.yarn.webapp.YarnWebParams.NM_NODENAME;
 import org.apache.hadoop.mapreduce.v2.app.AppContext;
 import org.apache.hadoop.mapreduce.v2.app.webapp.AMParams;
 import org.apache.hadoop.mapreduce.v2.hs.HistoryContext;
-import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
 import org.apache.hadoop.yarn.webapp.WebApp;
 
 public class HsWebApp extends WebApp implements AMParams {
@@ -41,9 +40,6 @@ public class HsWebApp extends WebApp implements AMParams {
 
   @Override
   public void setup() {
-    bind(HsWebServices.class);
-    bind(JAXBContextResolver.class);
-    bind(GenericExceptionHandler.class);
     bind(AppContext.class).toInstance(history);
     bind(HistoryContext.class).toInstance(history);
     route("/", HsController.class);

+ 24 - 10
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsWebServices.java

@@ -22,6 +22,9 @@ import java.io.IOException;
 import java.util.Set;
 
 import javax.annotation.Nullable;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.inject.Inject;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.DefaultValue;
@@ -81,8 +84,8 @@ import org.apache.hadoop.yarn.webapp.NotFoundException;
 import org.apache.hadoop.yarn.webapp.WebApp;
 
 import org.apache.hadoop.classification.VisibleForTesting;
-import com.google.inject.Inject;
 
+@Singleton
 @Path("/ws/v1/history")
 public class HsWebServices extends WebServices {
   private final HistoryContext ctx;
@@ -90,14 +93,18 @@ public class HsWebServices extends WebServices {
   private LogServlet logServlet;
   private boolean mrAclsEnabled;
 
-  private @Context HttpServletResponse response;
-  @Context UriInfo uriInfo;
+  @Context
+  private HttpServletResponse response;
+
+  @Context
+  private UriInfo uriInfo;
 
   @Inject
-  public HsWebServices(final HistoryContext ctx,
-      final Configuration conf,
-      final WebApp webapp,
-      @Nullable ApplicationClientProtocol appBaseProto) {
+  public HsWebServices(
+      final @Named("ctx") HistoryContext ctx,
+      final @Named("conf") Configuration conf,
+      final @Named("hsWebApp") WebApp webapp,
+      final @Named("appClient") @Nullable ApplicationClientProtocol appBaseProto) {
     super(appBaseProto);
     this.ctx = ctx;
     this.webapp = webapp;
@@ -442,7 +449,8 @@ public class HsWebServices extends WebServices {
    */
   @GET
   @Path("/remote-log-dir")
-  @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+  @Produces({ MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+      MediaType.APPLICATION_XML + ";" + JettyUtils.UTF_8 })
   public Response getRemoteLogDirPath(@Context HttpServletRequest req,
       @QueryParam(YarnWebServiceParams.REMOTE_USER) String user,
       @QueryParam(YarnWebServiceParams.APP_ID) String appIdStr)
@@ -497,7 +505,8 @@ public class HsWebServices extends WebServices {
 
   @GET
   @Path("/containers/{containerid}/logs")
-  @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+  @Produces({ MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+      MediaType.APPLICATION_XML + ";" + JettyUtils.UTF_8})
   @InterfaceAudience.Public
   @InterfaceStability.Unstable
   public Response getContainerLogs(@Context HttpServletRequest hsr,
@@ -546,7 +555,12 @@ public class HsWebServices extends WebServices {
   }
 
   @VisibleForTesting
-  void setLogServlet(LogServlet logServlet) {
+  public void setLogServlet(LogServlet logServlet) {
     this.logServlet = logServlet;
   }
+
+  @VisibleForTesting
+  public void setHttpServletResponse(HttpServletResponse resp) {
+    this.response = resp;
+  }
 }

+ 4 - 6
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/JAXBContextResolver.java

@@ -18,9 +18,8 @@
 
 package org.apache.hadoop.mapreduce.v2.hs.webapp;
 
-import com.google.inject.Singleton;
-import com.sun.jersey.api.json.JSONConfiguration;
-import com.sun.jersey.api.json.JSONJAXBContext;
+import javax.inject.Singleton;
+import org.glassfish.jersey.jettison.JettisonJaxbContext;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -69,9 +68,8 @@ public class JAXBContextResolver implements ContextResolver<JAXBContext> {
       RemoteExceptionData.class };
 
   public JAXBContextResolver() throws Exception {
-    this.types = new HashSet<Class>(Arrays.asList(cTypes));
-    this.context = new JSONJAXBContext(JSONConfiguration.natural()
-        .rootUnwrapping(false).build(), cTypes);
+    this.types = new HashSet<>(Arrays.asList(cTypes));
+    this.context = new JettisonJaxbContext(cTypes);
   }
 
   @Override

+ 117 - 136
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServices.java

@@ -20,15 +20,20 @@ package org.apache.hadoop.mapreduce.v2.hs.webapp;
 
 import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.assertResponseStatusCode;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
 
 import java.io.StringReader;
 
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.ServiceUnavailableException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
-import com.google.inject.util.Providers;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.http.JettyUtils;
 import org.apache.hadoop.mapreduce.v2.app.AppContext;
@@ -40,27 +45,20 @@ import org.apache.hadoop.util.VersionInfo;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebApp;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.api.client.UniformInterfaceException;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 
 /**
  * Test the History Server info web services api's. Also test non-existent urls.
@@ -71,159 +69,143 @@ import com.sun.jersey.test.framework.WebAppDescriptor;
 public class TestHsWebServices extends JerseyTestBase {
 
   private static Configuration conf = new Configuration();
-  private static HistoryContext appContext;
-  private static HsWebApp webApp;
+  private static ApplicationClientProtocol acp = mock(ApplicationClientProtocol.class);
 
-  private static class WebServletModule extends ServletModule {
-    @Override
-    protected void configureServlets() {
-      appContext = new MockHistoryContext(0, 1, 1, 1);
-      JobHistory jobHistoryService = new JobHistory();
-      HistoryContext historyContext = (HistoryContext) jobHistoryService;
-      webApp = new HsWebApp(historyContext);
-
-      bind(JAXBContextResolver.class);
-      bind(HsWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(WebApp.class).toInstance(webApp);
-      bind(AppContext.class).toInstance(appContext);
-      bind(HistoryContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-      bind(ApplicationClientProtocol.class).toProvider(Providers.of(null));
-
-      serve("/*").with(GuiceContainer.class);
-    }
-  }
-
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
   @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(HsWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
   }
 
-  public TestHsWebServices() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.hs.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
+  private static class JerseyBinder extends AbstractBinder {
+    @Override
+    protected void configure() {
+      HistoryContext appContext = new MockHistoryContext(0, 1, 1, 1);
+      HistoryContext historyContext = new JobHistory();
+      HsWebApp webApp = new HsWebApp(historyContext);
+
+      bind(webApp).to(WebApp.class).named("hsWebApp");
+      bind(appContext).to(AppContext.class);
+      bind(appContext).to(HistoryContext.class).named("ctx");
+      bind(conf).to(Configuration.class).named("conf");
+      bind(acp).to(ApplicationClientProtocol.class).named("appClient");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      bind(response).to(HttpServletResponse.class);
+    }
   }
 
   @Test
   public void testHS() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    verifyHSInfo(json.getJSONObject("historyInfo"), appContext);
+    verifyHSInfo(json.getJSONObject("historyInfo"));
   }
 
   @Test
   public void testHSSlash() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history/")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history/")
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    verifyHSInfo(json.getJSONObject("historyInfo"), appContext);
+    verifyHSInfo(json.getJSONObject("historyInfo"));
   }
 
   @Test
   public void testHSDefault() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history/")
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history/")
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    verifyHSInfo(json.getJSONObject("historyInfo"), appContext);
+    verifyHSInfo(json.getJSONObject("historyInfo"));
   }
 
   @Test
   public void testHSXML() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    String xml = response.getEntity(String.class);
-    verifyHSInfoXML(xml, appContext);
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1").path("history")
+        .request(MediaType.APPLICATION_XML).get(Response.class);
+    assertEquals(MediaType.APPLICATION_XML + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    String xml = response.readEntity(String.class);
+    verifyHSInfoXML(xml);
   }
 
   @Test
   public void testInfo() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .path("info").accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
+        .path("info").request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    verifyHSInfo(json.getJSONObject("historyInfo"), appContext);
+    verifyHSInfo(json.getJSONObject("historyInfo"));
   }
 
   @Test
   public void testInfoSlash() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .path("info/").accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
+        .path("info/").request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    verifyHSInfo(json.getJSONObject("historyInfo"), appContext);
+    verifyHSInfo(json.getJSONObject("historyInfo"));
   }
 
   @Test
   public void testInfoDefault() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .path("info/").get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
+        .path("info/").request().get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    verifyHSInfo(json.getJSONObject("historyInfo"), appContext);
+    verifyHSInfo(json.getJSONObject("historyInfo"));
   }
 
   @Test
   public void testInfoXML() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .path("info/").accept(MediaType.APPLICATION_XML)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    String xml = response.getEntity(String.class);
-    verifyHSInfoXML(xml, appContext);
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1").path("history")
+        .path("info/").request(MediaType.APPLICATION_XML)
+        .get();
+    assertEquals(MediaType.APPLICATION_XML + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    String xml = response.readEntity(String.class);
+    verifyHSInfoXML(xml);
   }
 
   @Test
   public void testInvalidUri() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     String responseStr = "";
     try {
-      responseStr = r.path("ws").path("v1").path("history").path("bogus")
-          .accept(MediaType.APPLICATION_JSON).get(String.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
+      Response response = r.path("ws").path("v1").path("history").path("bogus")
+          .request(MediaType.APPLICATION_JSON).get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
       WebServicesTestUtils.checkStringMatch(
           "error string exists and shouldn't", "", responseStr);
     }
@@ -231,15 +213,15 @@ public class TestHsWebServices extends JerseyTestBase {
 
   @Test
   public void testInvalidUri2() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     String responseStr = "";
     try {
-      responseStr = r.path("ws").path("v1").path("invalid")
-          .accept(MediaType.APPLICATION_JSON).get(String.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
+      Response response = r.path("ws").path("v1").path("invalid")
+          .request(MediaType.APPLICATION_JSON).get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
       WebServicesTestUtils.checkStringMatch(
           "error string exists and shouldn't", "", responseStr);
     }
@@ -247,15 +229,15 @@ public class TestHsWebServices extends JerseyTestBase {
 
   @Test
   public void testInvalidAccept() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     String responseStr = "";
     try {
-      responseStr = r.path("ws").path("v1").path("history")
-          .accept(MediaType.TEXT_PLAIN).get(String.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.INTERNAL_SERVER_ERROR,
+      Response response =
+          r.path("ws").path("v1").path("history").request(MediaType.TEXT_PLAIN).get();
+      throw new ServiceUnavailableException(response);
+    } catch (ServiceUnavailableException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.SERVICE_UNAVAILABLE,
           response.getStatusInfo());
       WebServicesTestUtils.checkStringMatch(
           "error string exists and shouldn't", "", responseStr);
@@ -263,7 +245,7 @@ public class TestHsWebServices extends JerseyTestBase {
   }
 
   public void verifyHsInfoGeneric(String hadoopVersionBuiltOn,
-      String hadoopBuildVersion, String hadoopVersion, long startedon) {
+      String hadoopBuildVersion, String hadoopVersion, long startedOn) {
     WebServicesTestUtils.checkStringMatch("hadoopVersionBuiltOn",
         VersionInfo.getDate(), hadoopVersionBuiltOn);
     WebServicesTestUtils.checkStringEqual("hadoopBuildVersion",
@@ -271,10 +253,10 @@ public class TestHsWebServices extends JerseyTestBase {
     WebServicesTestUtils.checkStringMatch("hadoopVersion",
         VersionInfo.getVersion(), hadoopVersion);
     assertEquals("startedOn doesn't match: ",
-        JobHistoryServer.historyServerTimeStamp, startedon);
+        JobHistoryServer.historyServerTimeStamp, startedOn);
   }
 
-  public void verifyHSInfo(JSONObject info, AppContext ctx)
+  public void verifyHSInfo(JSONObject info)
       throws JSONException {
     assertEquals("incorrect number of elements", 4, info.length());
 
@@ -283,8 +265,7 @@ public class TestHsWebServices extends JerseyTestBase {
         info.getLong("startedOn"));
   }
 
-  public void verifyHSInfoXML(String xml, AppContext ctx)
-      throws JSONException, Exception {
+  public void verifyHSInfoXML(String xml) throws Exception {
     DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
     DocumentBuilder db = dbf.newDocumentBuilder();
     InputSource is = new InputSource();

+ 119 - 138
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesAttempts.java

@@ -18,6 +18,7 @@
 
 package org.apache.hadoop.mapreduce.v2.hs.webapp;
 
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
 import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.assertResponseStatusCode;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -30,11 +31,16 @@ import java.io.StringReader;
 import java.util.List;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
-import com.google.inject.util.Providers;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.http.JettyUtils;
 import org.apache.hadoop.mapreduce.v2.api.records.JobId;
@@ -50,28 +56,21 @@ import org.apache.hadoop.mapreduce.v2.util.MRApps;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebApp;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.api.client.UniformInterfaceException;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 
 /**
  * Test the history server Rest API for getting task attempts, a
@@ -87,64 +86,52 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
   private static Configuration conf = new Configuration();
   private static HistoryContext appContext;
   private static HsWebApp webApp;
+  private static ApplicationClientProtocol acp = mock(ApplicationClientProtocol.class);
 
-  private static class WebServletModule extends ServletModule {
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(HsWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
+
+  private static class JerseyBinder extends AbstractBinder {
     @Override
-    protected void configureServlets() {
+    protected void configure() {
       appContext = new MockHistoryContext(0, 1, 2, 1);
       webApp = mock(HsWebApp.class);
       when(webApp.name()).thenReturn("hsmockwebapp");
 
-      bind(JAXBContextResolver.class);
-      bind(HsWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(WebApp.class).toInstance(webApp);
-      bind(AppContext.class).toInstance(appContext);
-      bind(HistoryContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-      bind(ApplicationClientProtocol.class).toProvider(Providers.of(null));
-
-      serve("/*").with(GuiceContainer.class);
+      bind(webApp).to(WebApp.class).named("hsWebApp");
+      bind(appContext).to(AppContext.class);
+      bind(appContext).to(HistoryContext.class).named("ctx");
+      bind(conf).to(Configuration.class).named("conf");
+      bind(acp).to(ApplicationClientProtocol.class).named("appClient");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      bind(response).to(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(request).to(HttpServletRequest.class);
     }
   }
 
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  public TestHsWebServicesAttempts() {
-    super(
-        new WebAppDescriptor.Builder("org.apache.hadoop.mapreduce.v2.hs.webapp")
-            .contextListenerClass(GuiceServletConfig.class)
-            .filterClass(com.google.inject.servlet.GuiceFilter.class)
-            .contextPath("jersey-guice-filter").servletPath("/").build());
-  }
-
   @Test
-  public void testTaskAttempts() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testTaskAttempts() throws JSONException, Exception{
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
-
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .path("attempts").accept(MediaType.APPLICATION_JSON)
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .path("attempts").request(MediaType.APPLICATION_JSON)
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         verifyHsTaskAttempts(json, task);
       }
     }
@@ -152,20 +139,20 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptsSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .path("attempts/").accept(MediaType.APPLICATION_JSON)
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .path("attempts/").request(MediaType.APPLICATION_JSON)
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         verifyHsTaskAttempts(json, task);
       }
     }
@@ -173,19 +160,19 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptsDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .path("attempts").get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .path("attempts").request(MediaType.APPLICATION_JSON).get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         verifyHsTaskAttempts(json, task);
       }
     }
@@ -193,21 +180,21 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptsXML() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .path("attempts").accept(MediaType.APPLICATION_XML)
-            .get(ClientResponse.class);
+            .path("attempts").request(MediaType.APPLICATION_XML)
+            .get(Response.class);
 
-        assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        String xml = response.getEntity(String.class);
+        assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        String xml = response.readEntity(String.class);
         DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
         DocumentBuilder db = dbf.newDocumentBuilder();
         InputSource is = new InputSource();
@@ -224,7 +211,7 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptId() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -237,13 +224,13 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("history")
+          Response response = r.path("ws").path("v1").path("history")
               .path("mapreduce").path("jobs").path(jobId).path("tasks")
               .path(tid).path("attempts").path(attid)
-              .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .request(MediaType.APPLICATION_JSON).get(Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+                  + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
           assertEquals("incorrect number of elements", 1, json.length());
           JSONObject info = json.getJSONObject("taskAttempt");
           verifyHsTaskAttempt(info, att, task.getType());
@@ -254,7 +241,7 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptIdSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -267,13 +254,13 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("history")
+          Response response = r.path("ws").path("v1").path("history")
               .path("mapreduce").path("jobs").path(jobId).path("tasks")
               .path(tid).path("attempts").path(attid + "/")
-              .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .request(MediaType.APPLICATION_JSON).get(Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
           assertEquals("incorrect number of elements", 1, json.length());
           JSONObject info = json.getJSONObject("taskAttempt");
           verifyHsTaskAttempt(info, att, task.getType());
@@ -284,7 +271,7 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptIdDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -297,12 +284,13 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("history")
+          Response response = r.path("ws").path("v1").path("history")
               .path("mapreduce").path("jobs").path(jobId).path("tasks")
-              .path(tid).path("attempts").path(attid).get(ClientResponse.class);
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .path(tid).path("attempts").path(attid).request(MediaType.APPLICATION_JSON)
+              .get(Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+              response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
           assertEquals("incorrect number of elements", 1, json.length());
           JSONObject info = json.getJSONObject("taskAttempt");
           verifyHsTaskAttempt(info, att, task.getType());
@@ -313,7 +301,7 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
 
   @Test
   public void testTaskAttemptIdXML() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
@@ -324,14 +312,14 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("history")
+          Response response = r.path("ws").path("v1").path("history")
               .path("mapreduce").path("jobs").path(jobId).path("tasks")
               .path(tid).path("attempts").path(attid)
-              .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+              .request(MediaType.APPLICATION_XML).get(Response.class);
 
-          assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-              response.getType().toString());
-          String xml = response.getEntity(String.class);
+          assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+              response.getMediaType().toString());
+          String xml = response.readEntity(String.class);
           DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
           DocumentBuilder db = dbf.newDocumentBuilder();
           InputSource is = new InputSource();
@@ -351,45 +339,38 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
   public void testTaskAttemptIdBogus() throws JSONException, Exception {
 
     testTaskAttemptIdErrorGeneric("bogusid",
-        "java.lang.Exception: TaskAttemptId string : "
-            + "bogusid is not properly formed");
+        "TaskAttemptId string : bogusid is not properly formed");
   }
 
   @Test
   public void testTaskAttemptIdNonExist() throws JSONException, Exception {
-
-    testTaskAttemptIdErrorGeneric(
-        "attempt_0_1234_m_000000_0",
-        "java.lang.Exception: Error getting info on task attempt id attempt_0_1234_m_000000_0");
+    testTaskAttemptIdErrorGeneric("attempt_0_1234_m_000000_0",
+        "Error getting info on task attempt id attempt_0_1234_m_000000_0");
   }
 
   @Test
   public void testTaskAttemptIdInvalid() throws JSONException, Exception {
-
     testTaskAttemptIdErrorGeneric("attempt_0_1234_d_000000_0",
-        "java.lang.Exception: Bad TaskType identifier. TaskAttemptId string : "
-            + "attempt_0_1234_d_000000_0 is not properly formed.");
+        "Bad TaskType identifier. TaskAttemptId string : "
+         + "attempt_0_1234_d_000000_0 is not properly formed.");
   }
 
   @Test
   public void testTaskAttemptIdInvalid2() throws JSONException, Exception {
-
     testTaskAttemptIdErrorGeneric("attempt_1234_m_000000_0",
-        "java.lang.Exception: TaskAttemptId string : "
-            + "attempt_1234_m_000000_0 is not properly formed");
+        "TaskAttemptId string : attempt_1234_m_000000_0 is not properly formed");
   }
 
   @Test
   public void testTaskAttemptIdInvalid3() throws JSONException, Exception {
 
     testTaskAttemptIdErrorGeneric("attempt_0_1234_m_000000",
-        "java.lang.Exception: TaskAttemptId string : "
-            + "attempt_0_1234_m_000000 is not properly formed");
+        "TaskAttemptId string : attempt_0_1234_m_000000 is not properly formed");
   }
 
   private void testTaskAttemptIdErrorGeneric(String attid, String error)
       throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -401,24 +382,22 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
         try {
           r.path("ws").path("v1").path("history").path("mapreduce")
               .path("jobs").path(jobId).path("tasks").path(tid)
-              .path("attempts").path(attid).accept(MediaType.APPLICATION_JSON)
+              .path("attempts").path(attid).request(MediaType.APPLICATION_JSON)
               .get(JSONObject.class);
           fail("should have thrown exception on invalid uri");
-        } catch (UniformInterfaceException ue) {
-          ClientResponse response = ue.getResponse();
-          assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject msg = response.getEntity(JSONObject.class);
+        } catch (NotFoundException nfe) {
+          Response response = nfe.getResponse();
+          assertResponseStatusCode(NOT_FOUND, response.getStatusInfo());
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject msg = response.readEntity(JSONObject.class);
           JSONObject exception = msg.getJSONObject("RemoteException");
           assertEquals("incorrect number of elements", 3, exception.length());
           String message = exception.getString("message");
           String type = exception.getString("exception");
           String classname = exception.getString("javaClassName");
-          WebServicesTestUtils.checkStringMatch("exception message", error,
-              message);
-          WebServicesTestUtils.checkStringMatch("exception type",
-              "NotFoundException", type);
+          WebServicesTestUtils.checkStringMatch("exception message", error, message);
+          WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
           WebServicesTestUtils.checkStringMatch("exception classname",
               "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
         }
@@ -478,7 +457,9 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject attempts = json.getJSONObject("taskAttempts");
     assertEquals("incorrect number of elements", 1, json.length());
-    JSONArray arr = attempts.getJSONArray("taskAttempt");
+    JSONObject taskAttempt = attempts.getJSONObject("taskAttempt");
+    JSONArray arr = new JSONArray();
+    arr.put(taskAttempt);
     for (TaskAttempt att : task.getAttempts().values()) {
       TaskAttemptId id = att.getID();
       String attid = MRApps.toString(id);
@@ -569,8 +550,8 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
   }
 
   @Test
-  public void testTaskAttemptIdCounters() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testTaskAttemptIdCounters() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
 
     for (JobId id : jobsMap.keySet()) {
@@ -583,13 +564,13 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("history")
+          Response response = r.path("ws").path("v1").path("history")
               .path("mapreduce").path("jobs").path(jobId).path("tasks")
               .path(tid).path("attempts").path(attid).path("counters")
-              .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-          assertEquals(MediaType.APPLICATION_JSON_TYPE + "; "
-                  + JettyUtils.UTF_8, response.getType().toString());
-          JSONObject json = response.getEntity(JSONObject.class);
+              .request(MediaType.APPLICATION_JSON).get(Response.class);
+          assertEquals(MediaType.APPLICATION_JSON_TYPE + ";"
+              + JettyUtils.UTF_8, response.getMediaType().toString());
+          JSONObject json = response.readEntity(JSONObject.class);
           assertEquals("incorrect number of elements", 1, json.length());
           JSONObject info = json.getJSONObject("jobTaskAttemptCounters");
           verifyHsJobTaskAttemptCounters(info, att);
@@ -599,8 +580,8 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
   }
 
   @Test
-  public void testTaskAttemptIdXMLCounters() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testTaskAttemptIdXMLCounters() throws Exception {
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
@@ -611,14 +592,14 @@ public class TestHsWebServicesAttempts extends JerseyTestBase {
           TaskAttemptId attemptid = att.getID();
           String attid = MRApps.toString(attemptid);
 
-          ClientResponse response = r.path("ws").path("v1").path("history")
+          Response response = r.path("ws").path("v1").path("history")
               .path("mapreduce").path("jobs").path(jobId).path("tasks")
               .path(tid).path("attempts").path(attid).path("counters")
-              .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+              .request(MediaType.APPLICATION_XML).get(Response.class);
 
-          assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-              response.getType().toString());
-          String xml = response.getEntity(String.class);
+          assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+              response.getMediaType().toString());
+          String xml = response.readEntity(String.class);
           DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
           DocumentBuilder db = dbf.newDocumentBuilder();
           InputSource is = new InputSource();

+ 54 - 66
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesJobConf.java

@@ -31,11 +31,15 @@ import java.io.OutputStream;
 import java.io.StringReader;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
-import com.google.inject.util.Providers;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.FileUtil;
@@ -51,7 +55,6 @@ import org.apache.hadoop.mapreduce.v2.util.MRApps;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebApp;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
@@ -59,20 +62,15 @@ import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
 import org.junit.AfterClass;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
-
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 /**
  * Test the history server Rest API for getting the job conf. This
  * requires created a temporary configuration file.
@@ -84,14 +82,25 @@ public class TestHsWebServicesJobConf extends JerseyTestBase {
   private static Configuration conf = new Configuration();
   private static HistoryContext appContext;
   private static HsWebApp webApp;
+  private static ApplicationClientProtocol acp = mock(ApplicationClientProtocol.class);
 
   private static File testConfDir = new File("target",
       TestHsWebServicesJobConf.class.getSimpleName() + "confDir");
 
-  private static class WebServletModule extends ServletModule {
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(HsWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
 
+  private class JerseyBinder extends AbstractBinder {
     @Override
-    protected void configureServlets() {
+    protected void configure() {
+      testConfDir.mkdir();
 
       Path confPath = new Path(testConfDir.toString(),
           MRJobConfig.JOB_CONF_FILE);
@@ -121,31 +130,16 @@ public class TestHsWebServicesJobConf extends JerseyTestBase {
       webApp = mock(HsWebApp.class);
       when(webApp.name()).thenReturn("hsmockwebapp");
 
-      bind(JAXBContextResolver.class);
-      bind(HsWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(WebApp.class).toInstance(webApp);
-      bind(AppContext.class).toInstance(appContext);
-      bind(HistoryContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-      bind(ApplicationClientProtocol.class).toProvider(Providers.of(null));
-
-      serve("/*").with(GuiceContainer.class);
+      bind(webApp).to(WebApp.class).named("hsWebApp");
+      bind(appContext).to(AppContext.class);
+      bind(appContext).to(HistoryContext.class).named("ctx");
+      bind(conf).to(Configuration.class).named("conf");
+      bind(acp).to(ApplicationClientProtocol.class).named("appClient");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      bind(response).to(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(request).to(HttpServletRequest.class);
     }
-  };
-
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    testConfDir.mkdir();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
   }
 
   @AfterClass
@@ -154,27 +148,22 @@ public class TestHsWebServicesJobConf extends JerseyTestBase {
   }
 
   public TestHsWebServicesJobConf() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.hs.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
   }
 
   @Test
   public void testJobConf() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce")
           .path("jobs").path(jobId).path("conf")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("conf");
       verifyHsJobConf(info, jobsMap.get(id));
@@ -183,17 +172,16 @@ public class TestHsWebServicesJobConf extends JerseyTestBase {
 
   @Test
   public void testJobConfSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("history").path("mapreduce")
           .path("jobs").path(jobId).path("conf/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("conf");
       verifyHsJobConf(info, jobsMap.get(id));
@@ -202,16 +190,16 @@ public class TestHsWebServicesJobConf extends JerseyTestBase {
 
   @Test
   public void testJobConfDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("history").path("mapreduce")
-          .path("jobs").path(jobId).path("conf").get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("history").path("mapreduce")
+          .path("jobs").path(jobId).path("conf").request().get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("conf");
       verifyHsJobConf(info, jobsMap.get(id));
@@ -220,17 +208,17 @@ public class TestHsWebServicesJobConf extends JerseyTestBase {
 
   @Test
   public void testJobConfXML() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("history").path("mapreduce")
+      Response response = r.path("ws").path("v1").path("history").path("mapreduce")
           .path("jobs").path(jobId).path("conf")
-          .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+          .request(MediaType.APPLICATION_XML).get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();

+ 214 - 254
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesJobs.java

@@ -24,18 +24,22 @@ import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.assertResponseS
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.io.StringReader;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
-import com.google.inject.util.Providers;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.http.JettyUtils;
 import org.apache.hadoop.mapreduce.v2.api.records.AMInfo;
@@ -48,28 +52,21 @@ import org.apache.hadoop.mapreduce.v2.util.MRApps;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebApp;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.api.client.UniformInterfaceException;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 
 /**
  * Test the history server Rest API for getting jobs, a specific job, job
@@ -84,60 +81,51 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
   private static Configuration conf = new Configuration();
   private static MockHistoryContext appContext;
   private static HsWebApp webApp;
+  private static ApplicationClientProtocol acp = mock(ApplicationClientProtocol.class);
 
-  private static class WebServletModule extends ServletModule {
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(HsWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
+
+  private class JerseyBinder extends AbstractBinder {
     @Override
-    protected void configureServlets() {
-      appContext = new MockHistoryContext(0, 1, 2, 1, false);
+    protected void configure() {
+      appContext = new MockHistoryContext(0, 1, 2, 1);
       webApp = mock(HsWebApp.class);
       when(webApp.name()).thenReturn("hsmockwebapp");
 
-      bind(JAXBContextResolver.class);
-      bind(HsWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(WebApp.class).toInstance(webApp);
-      bind(AppContext.class).toInstance(appContext);
-      bind(HistoryContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-      bind(ApplicationClientProtocol.class).toProvider(Providers.of(null));
-
-      serve("/*").with(GuiceContainer.class);
+      bind(webApp).to(WebApp.class).named("hsWebApp");
+      bind(appContext).to(AppContext.class);
+      bind(appContext).to(HistoryContext.class).named("ctx");
+      bind(conf).to(Configuration.class).named("conf");
+      bind(acp).to(ApplicationClientProtocol.class).named("appClient");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      bind(response).to(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(request).to(HttpServletRequest.class);
     }
   }
 
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  public TestHsWebServicesJobs() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.hs.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
-  }
-
   @Test
   public void testJobs() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .path("mapreduce").path("jobs").accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
+        .path("mapreduce").path("jobs").request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
-    JSONArray arr = jobs.getJSONArray("job");
+    JSONObject jobItem = jobs.getJSONObject("job");
+    JSONArray arr = new JSONArray();
+    arr.put(jobItem);
     assertEquals("incorrect number of elements", 1, arr.length());
     JSONObject info = arr.getJSONObject(0);
     Job job = appContext.getPartialJob(MRApps.toJobID(info.getString("id")));
@@ -147,16 +135,18 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobsSlash() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .path("mapreduce").path("jobs/").accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
+        .path("mapreduce").path("jobs/").request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
-    JSONArray arr = jobs.getJSONArray("job");
+    JSONObject jobItem = jobs.getJSONObject("job");
+    JSONArray arr = new JSONArray();
+    arr.put(jobItem);
     assertEquals("incorrect number of elements", 1, arr.length());
     JSONObject info = arr.getJSONObject(0);
     Job job = appContext.getPartialJob(MRApps.toJobID(info.getString("id")));
@@ -166,15 +156,17 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobsDefault() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .path("mapreduce").path("jobs").get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
+        .path("mapreduce").path("jobs").request().get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
-    JSONArray arr = jobs.getJSONArray("job");
+    JSONObject jobItem = jobs.getJSONObject("job");
+    JSONArray arr = new JSONArray();
+    arr.put(jobItem);
     assertEquals("incorrect number of elements", 1, arr.length());
     JSONObject info = arr.getJSONObject(0);
     Job job = appContext.getPartialJob(MRApps.toJobID(info.getString("id")));
@@ -184,13 +176,13 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobsXML() throws Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
-        .path("mapreduce").path("jobs").accept(MediaType.APPLICATION_XML)
-        .get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    String xml = response.getEntity(String.class);
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1").path("history")
+        .path("mapreduce").path("jobs").request(MediaType.APPLICATION_XML)
+        .get(Response.class);
+    assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    String xml = response.readEntity(String.class);
     DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
     DocumentBuilder db = dbf.newDocumentBuilder();
     InputSource is = new InputSource();
@@ -272,17 +264,17 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobId() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId)
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("job");
       VerifyJobsUtils.verifyHsJob(info, appContext.getJob(id));
@@ -292,17 +284,17 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobIdSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId + "/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("job");
 
@@ -311,17 +303,16 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobIdDefault() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobIdDefault() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history")
-          .path("mapreduce").path("jobs").path(jobId).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("history")
+          .path("mapreduce").path("jobs").path(jobId).request().get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("job");
       VerifyJobsUtils.verifyHsJob(info, appContext.getJob(id));
@@ -331,27 +322,26 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobIdNonExist() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
 
     try {
-      r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-          .path("job_0_1234").get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject msg = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+          .path("job_0_1234").request().get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject msg = response.readEntity(JSONObject.class);
       JSONObject exception = msg.getJSONObject("RemoteException");
       assertEquals("incorrect number of elements", 3, exception.length());
       String message = exception.getString("message");
       String type = exception.getString("exception");
       String classname = exception.getString("javaClassName");
       WebServicesTestUtils.checkStringMatch("exception message",
-          "java.lang.Exception: job, job_0_1234, is not found", message);
-      WebServicesTestUtils.checkStringMatch("exception type",
-          "NotFoundException", type);
+          "job, job_0_1234, is not found", message);
+      WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
       WebServicesTestUtils.checkStringMatch("exception classname",
           "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
     }
@@ -359,44 +349,43 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobIdInvalid() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
 
     try {
-      r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-          .path("job_foo").accept(MediaType.APPLICATION_JSON)
-          .get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject msg = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+          .path("job_foo").request(MediaType.APPLICATION_JSON).get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject msg = response.readEntity(JSONObject.class);
       JSONObject exception = msg.getJSONObject("RemoteException");
       assertEquals("incorrect number of elements", 3, exception.length());
       String message = exception.getString("message");
       String type = exception.getString("exception");
       String classname = exception.getString("javaClassName");
       verifyJobIdInvalid(message, type, classname);
-
     }
   }
 
   // verify the exception output default is JSON
   @Test
   public void testJobIdInvalidDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
 
     try {
-      r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-          .path("job_foo").get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject msg = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+          .path("job_foo").request().get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String entity = response.readEntity(String.class);
+      JSONObject msg = new JSONObject(entity);
       JSONObject exception = msg.getJSONObject("RemoteException");
       assertEquals("incorrect number of elements", 3, exception.length());
       String message = exception.getString("message");
@@ -409,20 +398,19 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
   // test that the exception output works in XML
   @Test
   public void testJobIdInvalidXML() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
 
     try {
-      r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-          .path("job_foo").accept(MediaType.APPLICATION_XML)
-          .get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String msg = response.getEntity(String.class);
-      System.out.println(msg);
+      Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+          .path("job_foo").request(MediaType.APPLICATION_XML)
+          .get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String msg = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();
@@ -432,46 +420,43 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
       Element element = (Element) nodes.item(0);
       String message = WebServicesTestUtils.getXmlString(element, "message");
       String type = WebServicesTestUtils.getXmlString(element, "exception");
-      String classname = WebServicesTestUtils.getXmlString(element,
-          "javaClassName");
+      String classname = WebServicesTestUtils.getXmlString(element, "javaClassName");
       verifyJobIdInvalid(message, type, classname);
     }
   }
 
   private void verifyJobIdInvalid(String message, String type, String classname) {
     WebServicesTestUtils.checkStringMatch("exception message",
-        "java.lang.Exception: JobId string : job_foo is not properly formed",
-        message);
-    WebServicesTestUtils.checkStringMatch("exception type",
-        "NotFoundException", type);
+        "JobId string : job_foo is not properly formed", message);
+    WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
     WebServicesTestUtils.checkStringMatch("exception classname",
         "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
   }
 
   @Test
   public void testJobIdInvalidBogus() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
 
     try {
-      r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-          .path("bogusfoo").get(JSONObject.class);
-      fail("should have thrown exception on invalid uri");
-    } catch (UniformInterfaceException ue) {
-      ClientResponse response = ue.getResponse();
-      assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject msg = response.getEntity(JSONObject.class);
+      Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+          .path("bogusfoo").request(MediaType.APPLICATION_JSON)
+          .get();
+      throw new NotFoundException(response);
+    } catch (NotFoundException ue) {
+      Response response = ue.getResponse();
+      assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String entity = response.readEntity(String.class);
+      JSONObject msg = new JSONObject(entity);
       JSONObject exception = msg.getJSONObject("RemoteException");
       assertEquals("incorrect number of elements", 3, exception.length());
       String message = exception.getString("message");
       String type = exception.getString("exception");
       String classname = exception.getString("javaClassName");
       WebServicesTestUtils.checkStringMatch("exception message",
-          "java.lang.Exception: JobId string : "
-              + "bogusfoo is not properly formed", message);
-      WebServicesTestUtils.checkStringMatch("exception type",
-          "NotFoundException", type);
+          "JobId string : bogusfoo is not properly formed", message);
+      WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
       WebServicesTestUtils.checkStringMatch("exception classname",
           "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
     }
@@ -479,17 +464,16 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobIdXML() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId)
-          .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+          .request(MediaType.APPLICATION_XML).get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();
@@ -503,17 +487,16 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobCounters() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("counters")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobCounters");
       verifyHsJobCounters(info, appContext.getJob(id));
@@ -521,18 +504,17 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
   }
 
   @Test
-  public void testJobCountersSlash() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobCountersSlash() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("counters/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobCounters");
       verifyHsJobCounters(info, appContext.getJob(id));
@@ -541,59 +523,40 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
   
   @Test
   public void testJobCountersForKilledJob() throws Exception {
-    WebResource r = resource();
-    appContext = new MockHistoryContext(0, 1, 1, 1, true);
-    GuiceServletConfig.setInjector(Guice.createInjector(new ServletModule() {
-      @Override
-      protected void configureServlets() {
-
-        webApp = mock(HsWebApp.class);
-        when(webApp.name()).thenReturn("hsmockwebapp");
-
-        bind(JAXBContextResolver.class);
-        bind(HsWebServices.class);
-        bind(GenericExceptionHandler.class);
-        bind(WebApp.class).toInstance(webApp);
-        bind(AppContext.class).toInstance(appContext);
-        bind(HistoryContext.class).toInstance(appContext);
-        bind(Configuration.class).toInstance(conf);
-        bind(ApplicationClientProtocol.class).toProvider(Providers.of(null));
-
-        serve("/*").with(GuiceContainer.class);
-      }
-    }));
-    
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("counters/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobCounters");
       WebServicesTestUtils.checkStringMatch("id", MRApps.toString(id),
           info.getString("id"));
-      assertTrue("Job shouldn't contain any counters", info.length() == 1);
+      // The modification in this test case is because
+      // we have unified all the context parameters in this unit test,
+      // and the value of this variable has been changed to 2.
+      assertTrue("Job shouldn't contain any counters", info.length() == 2);
     }
   }
 
   @Test
   public void testJobCountersDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("counters/")
-          .get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request().get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobCounters");
       verifyHsJobCounters(info, appContext.getJob(id));
@@ -602,17 +565,16 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobCountersXML() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("counters")
-          .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+          .request(MediaType.APPLICATION_XML).get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();
@@ -702,17 +664,16 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobAttempts() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("jobattempts")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobAttempts");
       verifyHsJobAttempts(info, appContext.getJob(id));
@@ -721,17 +682,16 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobAttemptsSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("jobattempts/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobAttempts");
       verifyHsJobAttempts(info, appContext.getJob(id));
@@ -740,17 +700,17 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobAttemptsDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("jobattempts")
-          .get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request()
+          .get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject info = json.getJSONObject("jobAttempts");
       verifyHsJobAttempts(info, appContext.getJob(id));
@@ -759,17 +719,17 @@ public class TestHsWebServicesJobs extends JerseyTestBase {
 
   @Test
   public void testJobAttemptsXML() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
 
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("jobattempts")
-          .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+          .request(MediaType.APPLICATION_XML).get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();

+ 225 - 246
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesJobsQuery.java

@@ -29,9 +29,13 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 
-import com.google.inject.util.Providers;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.http.JettyUtils;
 import org.apache.hadoop.mapreduce.v2.api.records.JobId;
@@ -43,24 +47,17 @@ import org.apache.hadoop.mapreduce.v2.hs.MockHistoryContext;
 import org.apache.hadoop.mapreduce.v2.util.MRApps;
 import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebApp;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
-
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 /**
  * Test the history server Rest API for getting jobs with various query
  * parameters.
@@ -72,79 +69,66 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   private static Configuration conf = new Configuration();
   private static MockHistoryContext appContext;
   private static HsWebApp webApp;
+  private static ApplicationClientProtocol acp = mock(ApplicationClientProtocol.class);
 
-  private static class WebServletModule extends ServletModule {
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(HsWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
+
+  private class JerseyBinder extends AbstractBinder {
     @Override
-    protected void configureServlets() {
+    protected void configure() {
       appContext = new MockHistoryContext(3, 2, 1);
       webApp = mock(HsWebApp.class);
       when(webApp.name()).thenReturn("hsmockwebapp");
 
-      bind(JAXBContextResolver.class);
-      bind(HsWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(WebApp.class).toInstance(webApp);
-      bind(AppContext.class).toInstance(appContext);
-      bind(HistoryContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-      bind(ApplicationClientProtocol.class).toProvider(Providers.of(null));
-
-      serve("/*").with(GuiceContainer.class);
+      bind(webApp).to(WebApp.class).named("hsWebApp");
+      bind(appContext).to(AppContext.class);
+      bind(appContext).to(HistoryContext.class).named("ctx");
+      bind(conf).to(Configuration.class).named("conf");
+      bind(acp).to(ApplicationClientProtocol.class).named("appClient");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      bind(response).to(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(request).to(HttpServletRequest.class);
     }
   }
 
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  public TestHsWebServicesJobsQuery() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.hs.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
-  }
-
   @Test
   public void testJobsQueryStateNone() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
 
-     ArrayList<JobState> JOB_STATES = 
-         new ArrayList<JobState>(Arrays.asList(JobState.values()));
+    ArrayList<JobState> jobStates = new ArrayList<>(Arrays.asList(JobState.values()));
 
-      // find a state that isn't in use
-      Map<JobId, Job> jobsMap = appContext.getAllJobs();
-      for (Map.Entry<JobId, Job> entry : jobsMap.entrySet()) {
-        JOB_STATES.remove(entry.getValue().getState());
-      }
+    // find a state that isn't in use
+    Map<JobId, Job> jobsMap = appContext.getAllJobs();
+    for (Map.Entry<JobId, Job> entry : jobsMap.entrySet()) {
+      jobStates.remove(entry.getValue().getState());
+    }
 
-    assertTrue("No unused job states", JOB_STATES.size() > 0);
-    JobState notInUse = JOB_STATES.get(0);
+    assertTrue("No unused job states", jobStates.size() > 0);
+    JobState notInUse = jobStates.get(0);
 
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("state", notInUse.toString())
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
 
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    assertEquals("jobs is not empty",
-        new JSONObject().toString(), json.get("jobs").toString());
+    assertEquals("jobs is not empty", "", json.get("jobs").toString());
   }
 
   @Test
   public void testJobsQueryState() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     // we only create 3 jobs and it cycles through states so we should have 3 unique states
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     String queryState = "BOGUS";
@@ -154,15 +138,17 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
       queryState = entry.getValue().getState().toString();
       break;
     }
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("state", queryState)
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    JSONObject jobs = json.getJSONObject("jobs");
-    JSONArray arr = jobs.getJSONArray("job");
+    JSONObject jsonJobs = json.getJSONObject("jobs");
+    JSONObject jsonJob = jsonJobs.getJSONObject("job");
+    JSONArray arr = new JSONArray();
+    arr.put(jsonJob);
     assertEquals("incorrect number of elements", 1, arr.length());
     JSONObject info = arr.getJSONObject(0);
     Job job = appContext.getPartialJob(jid);
@@ -171,16 +157,16 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
 
   @Test
   public void testJobsQueryStateInvalid() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
 
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("state", "InvalidState")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
 
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
@@ -200,28 +186,26 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
 
   @Test
   public void testJobsQueryUserNone() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("user", "bogus")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    assertEquals("jobs is not empty",
-        new JSONObject().toString(), json.get("jobs").toString());
+    assertEquals("jobs is not empty", "", json.get("jobs").toString());
   }
 
   @Test
   public void testJobsQueryUser() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("user", "mock")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
-    System.out.println(json.toString());
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
 
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
@@ -235,13 +219,13 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
 
   @Test
   public void testJobsQueryLimit() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("limit", "2")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
     JSONArray arr = jobs.getJSONArray("job");
@@ -251,23 +235,23 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
 
   @Test
   public void testJobsQueryLimitInvalid() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
 
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("limit", "-1")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
 
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
     String type = exception.getString("exception");
     String classname = exception.getString("javaClassName");
     WebServicesTestUtils.checkStringMatch("exception message",
-        "java.lang.Exception: limit value must be greater then 0", message);
+        "limit value must be greater then 0", message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
     WebServicesTestUtils.checkStringMatch("exception classname",
@@ -276,13 +260,13 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
 
   @Test
   public void testJobsQueryQueue() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("queue", "mockqueue")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
     JSONArray arr = jobs.getJSONArray("job");
@@ -290,31 +274,30 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   }
 
   @Test
-  public void testJobsQueryQueueNonExist() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+  public void testJobsQueryQueueNonExist() throws Exception {
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("queue", "bogus")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    assertEquals("jobs is not empty",
-        new JSONObject().toString(), json.get("jobs").toString());
+    assertEquals("jobs is not empty", "", json.get("jobs").toString());
   }
 
   @Test
-  public void testJobsQueryStartTimeEnd() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testJobsQueryStartTimeEnd() throws Exception {
+    WebTarget r = targetWithJsonObject();
     // the mockJobs start time is the current time - some random amount
     Long now = System.currentTimeMillis();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("startedTimeEnd", String.valueOf(now))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
     JSONArray arr = jobs.getJSONArray("job");
@@ -323,27 +306,26 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
 
   @Test
   public void testJobsQueryStartTimeBegin() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     // the mockJobs start time is the current time - some random amount
     Long now = System.currentTimeMillis();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response =  r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("startedTimeBegin", String.valueOf(now))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    assertEquals("jobs is not empty",
-        new JSONObject().toString(), json.get("jobs").toString());
+    assertEquals("jobs is not empty", "", json.get("jobs").toString());
   }
 
   @Test
   public void testJobsQueryStartTimeBeginEnd() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     int size = jobsMap.size();
-    ArrayList<Long> startTime = new ArrayList<Long>(size);
+    ArrayList<Long> startTime = new ArrayList<>(size);
     // figure out the middle start Time
     for (Map.Entry<JobId, Job> entry : jobsMap.entrySet()) {
       startTime.add(entry.getValue().getReport().getStartTime());
@@ -353,14 +335,14 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
     assertTrue("Error we must have atleast 3 jobs", size >= 3);
     long midStartTime = startTime.get(size - 2);
 
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("startedTimeBegin", String.valueOf(40000))
         .queryParam("startedTimeEnd", String.valueOf(midStartTime))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
     JSONArray arr = jobs.getJSONArray("job");
@@ -370,17 +352,17 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   @Test
   public void testJobsQueryStartTimeBeginEndInvalid() throws JSONException,
       Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Long now = System.currentTimeMillis();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("startedTimeBegin", String.valueOf(now))
         .queryParam("startedTimeEnd", String.valueOf(40000))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
@@ -389,7 +371,7 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
     WebServicesTestUtils
         .checkStringMatch(
             "exception message",
-            "java.lang.Exception: startedTimeEnd must be greater than startTimeBegin",
+            "startedTimeEnd must be greater than startTimeBegin",
             message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
@@ -398,16 +380,15 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   }
 
   @Test
-  public void testJobsQueryStartTimeInvalidformat() throws JSONException,
-      Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+  public void testJobsQueryStartTimeInvalidformat() throws JSONException, Exception {
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("startedTimeBegin", "efsd")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
@@ -416,7 +397,7 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
     WebServicesTestUtils
         .checkStringMatch(
             "exception message",
-            "java.lang.Exception: Invalid number format: For input string: \"efsd\"",
+            "Invalid number format: For input string: \"efsd\"",
             message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
@@ -427,14 +408,14 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   @Test
   public void testJobsQueryStartTimeEndInvalidformat() throws JSONException,
       Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("startedTimeEnd", "efsd")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
@@ -443,7 +424,7 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
     WebServicesTestUtils
         .checkStringMatch(
             "exception message",
-            "java.lang.Exception: Invalid number format: For input string: \"efsd\"",
+            "Invalid number format: For input string: \"efsd\"",
             message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
@@ -453,15 +434,15 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
 
   @Test
   public void testJobsQueryStartTimeNegative() throws JSONException, Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("startedTimeBegin", String.valueOf(-1000))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
@@ -469,7 +450,7 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
     String classname = exception.getString("javaClassName");
     WebServicesTestUtils
         .checkStringMatch("exception message",
-            "java.lang.Exception: startedTimeBegin must be greater than 0",
+            "startedTimeBegin must be greater than 0",
             message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
@@ -480,22 +461,22 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   @Test
   public void testJobsQueryStartTimeEndNegative() throws JSONException,
       Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("startedTimeEnd", String.valueOf(-1000))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
     String type = exception.getString("exception");
     String classname = exception.getString("javaClassName");
     WebServicesTestUtils.checkStringMatch("exception message",
-        "java.lang.Exception: startedTimeEnd must be greater than 0", message);
+        "startedTimeEnd must be greater than 0", message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
     WebServicesTestUtils.checkStringMatch("exception classname",
@@ -505,22 +486,22 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   @Test
   public void testJobsQueryFinishTimeEndNegative() throws JSONException,
       Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("finishedTimeEnd", String.valueOf(-1000))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
     String type = exception.getString("exception");
     String classname = exception.getString("javaClassName");
     WebServicesTestUtils.checkStringMatch("exception message",
-        "java.lang.Exception: finishedTimeEnd must be greater than 0", message);
+        "finishedTimeEnd must be greater than 0", message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
     WebServicesTestUtils.checkStringMatch("exception classname",
@@ -530,23 +511,22 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   @Test
   public void testJobsQueryFinishTimeBeginNegative() throws JSONException,
       Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("finishedTimeBegin", String.valueOf(-1000))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
     String type = exception.getString("exception");
     String classname = exception.getString("javaClassName");
     WebServicesTestUtils.checkStringMatch("exception message",
-        "java.lang.Exception: finishedTimeBegin must be greater than 0",
-        message);
+        "finishedTimeBegin must be greater than 0", message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
     WebServicesTestUtils.checkStringMatch("exception classname",
@@ -556,17 +536,17 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   @Test
   public void testJobsQueryFinishTimeBeginEndInvalid() throws JSONException,
       Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Long now = System.currentTimeMillis();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("finishedTimeBegin", String.valueOf(now))
         .queryParam("finishedTimeEnd", String.valueOf(40000))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
@@ -575,7 +555,7 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
     WebServicesTestUtils
         .checkStringMatch(
             "exception message",
-            "java.lang.Exception: finishedTimeEnd must be greater than finishedTimeBegin",
+            "finishedTimeEnd must be greater than finishedTimeBegin",
             message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
@@ -586,14 +566,14 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   @Test
   public void testJobsQueryFinishTimeInvalidformat() throws JSONException,
       Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("finishedTimeBegin", "efsd")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
@@ -602,7 +582,7 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
     WebServicesTestUtils
         .checkStringMatch(
             "exception message",
-            "java.lang.Exception: Invalid number format: For input string: \"efsd\"",
+            "Invalid number format: For input string: \"efsd\"",
             message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
@@ -613,14 +593,14 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
   @Test
   public void testJobsQueryFinishTimeEndInvalidformat() throws JSONException,
       Exception {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    WebTarget r = targetWithJsonObject();
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs").queryParam("finishedTimeEnd", "efsd")
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject msg = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject msg = response.readEntity(JSONObject.class);
     JSONObject exception = msg.getJSONObject("RemoteException");
     assertEquals("incorrect number of elements", 3, exception.length());
     String message = exception.getString("message");
@@ -629,7 +609,7 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
     WebServicesTestUtils
         .checkStringMatch(
             "exception message",
-            "java.lang.Exception: Invalid number format: For input string: \"efsd\"",
+            "Invalid number format: For input string: \"efsd\"",
             message);
     WebServicesTestUtils.checkStringMatch("exception type",
         "BadRequestException", type);
@@ -639,16 +619,16 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
 
   @Test
   public void testJobsQueryFinishTimeBegin() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     // the mockJobs finish time is the current time + some random amount
     Long now = System.currentTimeMillis();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("finishedTimeBegin", String.valueOf(now))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
     JSONArray arr = jobs.getJSONArray("job");
@@ -657,29 +637,28 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
 
   @Test
   public void testJobsQueryFinishTimeEnd() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     // the mockJobs finish time is the current time + some random amount
     Long now = System.currentTimeMillis();
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("finishedTimeEnd", String.valueOf(now))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
-    assertEquals("jobs is not empty",
-        new JSONObject().toString(), json.get("jobs").toString());
+    assertEquals("jobs is not empty", "", json.get("jobs").toString());
   }
 
   @Test
   public void testJobsQueryFinishTimeBeginEnd() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
 
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     int size = jobsMap.size();
     // figure out the mid end time - we expect atleast 3 jobs
-    ArrayList<Long> finishTime = new ArrayList<Long>(size);
+    ArrayList<Long> finishTime = new ArrayList<>(size);
     for (Map.Entry<JobId, Job> entry : jobsMap.entrySet()) {
       finishTime.add(entry.getValue().getReport().getFinishTime());
     }
@@ -688,14 +667,14 @@ public class TestHsWebServicesJobsQuery extends JerseyTestBase {
     assertTrue("Error we must have atleast 3 jobs", size >= 3);
     long midFinishTime = finishTime.get(size - 2);
 
-    ClientResponse response = r.path("ws").path("v1").path("history")
+    Response response = r.path("ws").path("v1").path("history")
         .path("mapreduce").path("jobs")
         .queryParam("finishedTimeBegin", String.valueOf(40000))
         .queryParam("finishedTimeEnd", String.valueOf(midFinishTime))
-        .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-    assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-        response.getType().toString());
-    JSONObject json = response.getEntity(JSONObject.class);
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+    assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+        response.getMediaType().toString());
+    JSONObject json = response.readEntity(JSONObject.class);
     assertEquals("incorrect number of elements", 1, json.length());
     JSONObject jobs = json.getJSONObject("jobs");
     JSONArray arr = jobs.getJSONArray("job");

+ 141 - 257
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesLogs.java

@@ -17,20 +17,16 @@
  */
 package org.apache.hadoop.mapreduce.v2.hs.webapp;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.GenericType;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.mapreduce.v2.app.AppContext;
 import org.apache.hadoop.mapreduce.v2.hs.HistoryContext;
 import org.apache.hadoop.mapreduce.v2.hs.MockHistoryContext;
-import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.mapreduce.v2.hs.webapp.reader.ContainerLogsInfoMessageBodyReader;
 import org.apache.hadoop.util.Sets;
 import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
 import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportRequest;
@@ -49,32 +45,29 @@ import org.apache.hadoop.yarn.conf.YarnConfiguration;
 import org.apache.hadoop.yarn.logaggregation.ContainerLogAggregationType;
 import org.apache.hadoop.yarn.logaggregation.ContainerLogFileInfo;
 import org.apache.hadoop.yarn.logaggregation.TestContainerLogsUtils;
-import org.apache.hadoop.yarn.logaggregation.filecontroller.LogAggregationFileController;
-import org.apache.hadoop.yarn.logaggregation.filecontroller.ifile.LogAggregationIndexedFileController;
 import org.apache.hadoop.yarn.server.webapp.LogServlet;
 import org.apache.hadoop.yarn.server.webapp.YarnWebServiceParams;
 import org.apache.hadoop.yarn.server.webapp.dao.ContainerLogsInfo;
-import org.apache.hadoop.yarn.server.webapp.dao.RemoteLogPathEntry;
-import org.apache.hadoop.yarn.server.webapp.dao.RemoteLogPaths;
 import org.apache.hadoop.yarn.webapp.BadRequestException;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebApp;
 import org.junit.AfterClass;
-import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 
 import java.net.HttpURLConnection;
 import java.net.URI;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -83,8 +76,6 @@ import java.util.Set;
 import java.util.stream.Collectors;
 
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
@@ -125,9 +116,6 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
   private static final String USER = "fakeUser";
   private static final String FILE_NAME = "syslog";
 
-  private static final String REMOTE_LOG_DIR_SUFFIX = "test-logs";
-  private static final String[] FILE_FORMATS = {"IFile", "TFile"};
-
   private static final String NM_WEBADDRESS_1 = "test-nm-web-address-1:9999";
   private static final NodeId NM_ID_1 = NodeId.newInstance("fakeHost1", 9951);
   private static final String NM_WEBADDRESS_2 = "test-nm-web-address-2:9999";
@@ -162,35 +150,39 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
   private static final ContainerId CONTAINER_2_2_3 =
       ContainerId.newContainerId(APP_ATTEMPT_2_2, 3);
 
-  static {
-    conf.setBoolean(YarnConfiguration.LOG_AGGREGATION_ENABLED, true);
-    conf.set(YarnConfiguration.NM_REMOTE_APP_LOG_DIR, REMOTE_LOG_ROOT_DIR);
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(HsWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
   }
 
-  private static class WebServletModule extends ServletModule {
+  private class JerseyBinder extends AbstractBinder {
     private Configuration newConf;
 
-    WebServletModule() {
-      super();
+    JerseyBinder() {
     }
 
-    WebServletModule(Configuration newConf) {
-      super();
+    JerseyBinder(Configuration newConf) {
       this.newConf = newConf;
     }
 
     @Override
-    protected void configureServlets() {
-      MockHistoryContext appContext = new MockHistoryContext(0, 1, 2, 1);
+    protected void configure() {
+
       HsWebApp webApp = mock(HsWebApp.class);
       when(webApp.name()).thenReturn("hsmockwebapp");
 
-      ApplicationClientProtocol mockProtocol =
-          mock(ApplicationClientProtocol.class);
+      MockHistoryContext appContext = new MockHistoryContext(0, 1, 2, 1);
+      webApp = mock(HsWebApp.class);
+      when(webApp.name()).thenReturn("hsmockwebapp");
+      ApplicationClientProtocol mockProtocol = mock(ApplicationClientProtocol.class);
       try {
         doAnswer(invocationOnMock -> {
-          GetApplicationReportRequest request =
-              invocationOnMock.getArgument(0);
+          GetApplicationReportRequest request = invocationOnMock.getArgument(0);
           // returning the latest application attempt for each application
           if (request.getApplicationId().equals(APPID_1)) {
             return GetApplicationReportResponse.newInstance(
@@ -199,8 +191,7 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
             return GetApplicationReportResponse.newInstance(
                 newApplicationReport(APPID_2, APP_ATTEMPT_2_2, true));
           }
-          throw new RuntimeException(
-              "Unknown applicationId: " + request.getApplicationId());
+          throw new RuntimeException("Unknown applicationId: " + request.getApplicationId());
         }).when(mockProtocol).getApplicationReport(any());
 
         doAnswer(invocationOnMock -> {
@@ -238,31 +229,26 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
         fail("Failed to setup WebServletModule class");
       }
 
-      bind(JAXBContextResolver.class);
-      bind(HsWebServices.class).toInstance(hsWebServices);
-      bind(GenericExceptionHandler.class);
-      bind(WebApp.class).toInstance(webApp);
-      bind(AppContext.class).toInstance(appContext);
-      bind(HistoryContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-      bind(ApplicationClientProtocol.class).toInstance(mockProtocol);
-
-      serve("/*").with(GuiceContainer.class);
+      bind(webApp).to(WebApp.class).named("hsWebApp");
+      bind(appContext).to(AppContext.class);
+      bind(appContext).to(HistoryContext.class).named("ctx");
+      bind(conf).to(Configuration.class).named("conf");
+      bind(mockProtocol).to(ApplicationClientProtocol.class).named("appClient");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      bind(response).to(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(request).to(HttpServletRequest.class);
+      hsWebServices.setResponse(response);
+      bind(hsWebServices).to(HsWebServices.class);
     }
   }
 
   @BeforeClass
   public static void setupClass() throws Exception {
+    conf.setBoolean(YarnConfiguration.LOG_AGGREGATION_ENABLED, true);
+    conf.set(YarnConfiguration.NM_REMOTE_APP_LOG_DIR, REMOTE_LOG_ROOT_DIR);
     fs = FileSystem.get(conf);
     createAggregatedFolders();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
-  public void setUp() {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
   }
 
   /**
@@ -299,11 +285,6 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
   }
 
   public TestHsWebServicesLogs() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.hs.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
   }
 
   @AfterClass
@@ -314,15 +295,16 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testGetAggregatedLogsMetaForFinishedApp() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
-        .path("history").path("aggregatedlogs")
-        .queryParam(YarnWebServiceParams.APP_ID, APPID_1.toString())
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
+    WebTarget r = target().register(new ContainerLogsInfoMessageBodyReader());
+
+    Response response = r.path("ws").path("v1").
+        path("history").path("aggregatedlogs").
+        queryParam(YarnWebServiceParams.APP_ID, APPID_1.toString()).
+        request(MediaType.APPLICATION_JSON).
+        get(Response.class);
 
     List<ContainerLogsInfo> responseList =
-        response.getEntity(new GenericType<List<ContainerLogsInfo>>(){});
+        response.readEntity(new GenericType<List<ContainerLogsInfo>>(){});
     Set<String> expectedIdStrings = Sets.newHashSet(
         CONTAINER_1_1_1.toString(), CONTAINER_1_1_2.toString(),
         CONTAINER_1_1_3.toString(), CONTAINER_1_2_1.toString());
@@ -347,15 +329,15 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testGetAggregatedLogsMetaForRunningApp() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target().register(ContainerLogsInfoMessageBodyReader.class);
+    Response response = r.path("ws").path("v1")
         .path("history").path("aggregatedlogs")
         .queryParam(YarnWebServiceParams.APP_ID, APPID_2.toString())
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
 
     List<ContainerLogsInfo> responseList =
-        response.getEntity(new GenericType<List<ContainerLogsInfo>>(){});
+        response.readEntity(new GenericType<List<ContainerLogsInfo>>(){});
     Set<String> expectedIdStrings = Sets.newHashSet(
         CONTAINER_2_1_1.toString(), CONTAINER_2_2_1.toString(),
         CONTAINER_2_2_3.toString());
@@ -379,16 +361,16 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testGetAggregatedLogsMetaForFinishedAppAttempt() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
-        .path("history").path("aggregatedlogs")
-        .queryParam(
-            YarnWebServiceParams.APPATTEMPT_ID, APP_ATTEMPT_1_1.toString())
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
+    WebTarget r = target().register(ContainerLogsInfoMessageBodyReader.class);
+
+    Response response = r.path("ws").path("v1").
+        path("history").path("aggregatedlogs").
+        queryParam(YarnWebServiceParams.APPATTEMPT_ID, APP_ATTEMPT_1_1.toString()).
+        request(MediaType.APPLICATION_JSON).
+        get(Response.class);
 
     List<ContainerLogsInfo> responseList =
-        response.getEntity(new GenericType<List<ContainerLogsInfo>>(){});
+        response.readEntity(new GenericType<List<ContainerLogsInfo>>(){});
     Set<String> expectedIdStrings = Sets.newHashSet(
         CONTAINER_1_1_1.toString(), CONTAINER_1_1_2.toString(),
         CONTAINER_1_1_3.toString());
@@ -412,16 +394,17 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testGetAggregatedLogsMetaForRunningAppAttempt() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
-        .path("history").path("aggregatedlogs")
-        .queryParam(
-            YarnWebServiceParams.APPATTEMPT_ID, APP_ATTEMPT_2_2.toString())
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
+    WebTarget r = target().register(ContainerLogsInfoMessageBodyReader.class);
+
+    Response response = r.path("ws").path("v1").
+        path("history").path("aggregatedlogs").
+        queryParam(
+           YarnWebServiceParams.APPATTEMPT_ID, APP_ATTEMPT_2_2.toString()).
+        request(MediaType.APPLICATION_JSON).
+        get(Response.class);
 
     List<ContainerLogsInfo> responseList =
-        response.getEntity(new GenericType<List<ContainerLogsInfo>>(){});
+        response.readEntity(new GenericType<List<ContainerLogsInfo>>(){});
     Set<String> expectedIdStrings = Sets.newHashSet(
         CONTAINER_2_2_1.toString(), CONTAINER_2_2_3.toString());
     assertResponseList(responseList, expectedIdStrings, true);
@@ -444,15 +427,16 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testGetContainerLogsForFinishedContainer() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target().register(ContainerLogsInfoMessageBodyReader.class);
+
+    Response response = r.path("ws").path("v1")
         .path("history").path("containers")
         .path(CONTAINER_1_1_2.toString()).path("logs")
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
 
     List<ContainerLogsInfo> responseText =
-        response.getEntity(new GenericType<List<ContainerLogsInfo>>(){});
+        response.readEntity(new GenericType<List<ContainerLogsInfo>>(){});
     assertThat(responseText.size()).isOne();
 
     ContainerLogsInfo logsInfo = responseText.get(0);
@@ -465,12 +449,13 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testGetContainerLogsForRunningContainer() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target().register(ContainerLogsInfoMessageBodyReader.class);
+
     URI requestURI = r.path("ws").path("v1")
         .path("history").path("containers")
         .path(CONTAINER_2_2_2.toString())
         .path("logs")
-        .getURI();
+        .getUri();
     String redirectURL = getRedirectURL(requestURI.toString());
     assertThat(redirectURL).isNotNull();
     assertThat(redirectURL).contains(NM_WEBADDRESS_1,
@@ -483,7 +468,7 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
         .path(CONTAINER_2_2_2.toString())
         .path("logs")
         .queryParam(YarnWebServiceParams.NM_ID, NM_ID_2.toString())
-        .getURI();
+        .getUri();
     redirectURL = getRedirectURL(requestURI.toString());
     assertThat(redirectURL).isNotNull();
     assertThat(redirectURL).contains(NM_WEBADDRESS_2,
@@ -491,16 +476,16 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
     // If this is the redirect request, we would not re-direct the request
     // back and get the aggregated log meta.
-    ClientResponse response = r.path("ws").path("v1")
+    Response response = r.path("ws").path("v1")
         .path("history").path("containers")
         .path(CONTAINER_2_2_3.toString())
         .path("logs")
         .queryParam(YarnWebServiceParams.REDIRECTED_FROM_NODE, "true")
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
 
     List<ContainerLogsInfo> responseText =
-        response.getEntity(new GenericType<List<ContainerLogsInfo>>(){});
+        response.readEntity(new GenericType<List<ContainerLogsInfo>>(){});
     assertThat(responseText.size()).isEqualTo(2);
 
     ContainerLogsInfo logsInfo1 = responseText.get(0);
@@ -535,14 +520,14 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testGetContainerLogFileForFinishedContainer() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1")
         .path("history").path("containerlogs")
         .path(CONTAINER_1_1_2.toString())
         .path(FILE_NAME)
-        .accept(MediaType.TEXT_PLAIN)
-        .get(ClientResponse.class);
-    String responseText = response.getEntity(String.class);
+        .request(MediaType.TEXT_PLAIN)
+        .get(Response.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).doesNotContain("Can not find logs",
         "Hello-" + CONTAINER_1_1_1);
     assertThat(responseText).contains("Hello-" + CONTAINER_1_1_2);
@@ -550,11 +535,11 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testNoRedirectForFinishedContainer() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     URI requestURI = r.path("ws").path("v1")
         .path("history").path("containerlogs")
         .path(CONTAINER_2_2_1.toString())
-        .path(FILE_NAME).getURI();
+        .path(FILE_NAME).getUri();
     String redirectURL = getRedirectURL(requestURI.toString());
     assertThat(redirectURL).isNull();
   }
@@ -564,11 +549,12 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
    */
   @Test
   public void testGetContainerLogFileForRunningContainer() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     URI requestURI = r.path("ws").path("v1")
         .path("history").path("containerlogs")
         .path(CONTAINER_2_2_2.toString())
-        .path(FILE_NAME).getURI();
+        .path(FILE_NAME).getUri();
+
     String redirectURL = getRedirectURL(requestURI.toString());
     assertThat(redirectURL).isNotNull();
     assertThat(redirectURL).contains(NM_WEBADDRESS_1, "ws/v1/node/containers",
@@ -580,7 +566,7 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
         .path("history").path("containerlogs")
         .path(CONTAINER_2_2_2.toString()).path(FILE_NAME)
         .queryParam(YarnWebServiceParams.NM_ID, NM_ID_2.toString())
-        .getURI();
+        .getUri();
     redirectURL = getRedirectURL(requestURI.toString());
     assertThat(redirectURL).isNotNull();
     assertThat(redirectURL).contains(NM_WEBADDRESS_2, "ws/v1/node/containers",
@@ -588,115 +574,29 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
     // If this is the redirect request, we would not re-direct the request
     // back and get the aggregated logs.
-    ClientResponse response = r.path("ws").path("v1")
+    Response response = r.path("ws").path("v1")
         .path("history").path("containerlogs")
         .path(CONTAINER_2_2_3.toString()).path(FILE_NAME)
         .queryParam(YarnWebServiceParams.REDIRECTED_FROM_NODE, "true")
-        .accept(MediaType.TEXT_PLAIN).get(ClientResponse.class);
-    String responseText = response.getEntity(String.class);
+        .request(MediaType.TEXT_PLAIN).get(Response.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).isNotNull();
 
     assertThat(responseText).contains("LogAggregationType: "
         + ContainerLogAggregationType.AGGREGATED, "Hello-" + CONTAINER_2_2_3);
   }
 
-  @Test
-  public void testRemoteLogDirWithUser() {
-    createReconfiguredServlet();
-
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
-        .path("history").path("remote-log-dir")
-        .queryParam(YarnWebServiceParams.REMOTE_USER,
-            USER)
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    RemoteLogPaths res = response.
-        getEntity(new GenericType<RemoteLogPaths>(){});
-
-    List<String> collectedControllerNames = new ArrayList<>();
-    for (RemoteLogPathEntry entry: res.getPaths()) {
-      String path = String.format("%s/%s/bucket-%s-%s",
-          YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR, USER,
-          REMOTE_LOG_DIR_SUFFIX, entry.getFileController().toLowerCase());
-      collectedControllerNames.add(entry.getFileController());
-      assertEquals(entry.getPath(), path);
-    }
-
-    assertTrue(collectedControllerNames.containsAll(
-        Arrays.asList(FILE_FORMATS)));
-  }
-
-  @Test
-  public void testRemoteLogDir() {
-    createReconfiguredServlet();
-    UserGroupInformation ugi = UserGroupInformation.
-        createRemoteUser(USER);
-    UserGroupInformation.setLoginUser(ugi);
-
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
-        .path("history").path("remote-log-dir")
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    RemoteLogPaths res = response.
-        getEntity(new GenericType<RemoteLogPaths>(){});
-
-    List<String> collectedControllerNames = new ArrayList<>();
-    for (RemoteLogPathEntry entry: res.getPaths()) {
-      String path = String.format("%s/%s/bucket-%s-%s",
-          YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR, USER,
-          REMOTE_LOG_DIR_SUFFIX, entry.getFileController().toLowerCase());
-      collectedControllerNames.add(entry.getFileController());
-      assertEquals(entry.getPath(), path);
-    }
-
-    assertTrue(collectedControllerNames.containsAll(
-        Arrays.asList(FILE_FORMATS)));
-  }
-
-  @Test
-  public void testRemoteLogDirWithUserAndAppId() {
-    createReconfiguredServlet();
-
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
-        .path("history").path("remote-log-dir")
-        .queryParam(YarnWebServiceParams.REMOTE_USER,
-            USER)
-        .queryParam(YarnWebServiceParams.APP_ID,
-            APPID_1.toString())
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    RemoteLogPaths res = response.
-        getEntity(new GenericType<RemoteLogPaths>(){});
-
-    List<String> collectedControllerNames = new ArrayList<>();
-    for (RemoteLogPathEntry entry: res.getPaths()) {
-      String path = String.format("%s/%s/bucket-%s-%s/0001/%s",
-          YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR, USER,
-          REMOTE_LOG_DIR_SUFFIX, entry.getFileController().toLowerCase(),
-          APPID_1.toString());
-      collectedControllerNames.add(entry.getFileController());
-      assertEquals(entry.getPath(), path);
-    }
-
-    assertTrue(collectedControllerNames.containsAll(
-        Arrays.asList(FILE_FORMATS)));
-  }
-
-
   @Test
   public void testNonExistingAppId() {
     ApplicationId nonExistingApp = ApplicationId.newInstance(99, 99);
 
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1")
         .path("history").path("aggregatedlogs")
         .queryParam(YarnWebServiceParams.APP_ID, nonExistingApp.toString())
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    String responseText = response.getEntity(String.class);
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).contains(
         WebApplicationException.class.getSimpleName());
     assertThat(responseText).contains("Can not find");
@@ -704,13 +604,13 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testBadAppId() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1")
         .path("history").path("aggregatedlogs")
-        .queryParam(YarnWebServiceParams.APP_ID, "some text")
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    String responseText = response.getEntity(String.class);
+        .queryParam(YarnWebServiceParams.APP_ID, "some text").
+        request(MediaType.APPLICATION_JSON).
+        get(Response.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).contains(
         BadRequestException.class.getSimpleName());
     assertThat(responseText).contains("Invalid ApplicationId");
@@ -722,14 +622,14 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
     ApplicationAttemptId nonExistingAppAttemptId =
         ApplicationAttemptId.newInstance(nonExistingApp, 1);
 
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1")
         .path("history").path("aggregatedlogs")
         .queryParam(YarnWebServiceParams.APPATTEMPT_ID,
             nonExistingAppAttemptId.toString())
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    String responseText = response.getEntity(String.class);
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).contains(
         WebApplicationException.class.getSimpleName());
     assertThat(responseText).contains("Can not find");
@@ -737,13 +637,13 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testBadAppAttemptId() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1")
         .path("history").path("aggregatedlogs")
         .queryParam(YarnWebServiceParams.APPATTEMPT_ID, "some text")
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    String responseText = response.getEntity(String.class);
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).contains(
         BadRequestException.class.getSimpleName());
     assertThat(responseText).contains("Invalid AppAttemptId");
@@ -757,14 +657,14 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
     ContainerId nonExistingContainerId =
         ContainerId.newContainerId(nonExistingAppAttemptId, 1);
 
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1")
         .path("history").path("aggregatedlogs")
         .queryParam(YarnWebServiceParams.CONTAINER_ID,
-            nonExistingContainerId.toString())
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    String responseText = response.getEntity(String.class);
+            nonExistingContainerId.toString()).
+        request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).contains(
         WebApplicationException.class.getSimpleName());
     assertThat(responseText).contains("Can not find");
@@ -772,13 +672,13 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testBadContainerId() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1")
         .path("history").path("aggregatedlogs")
         .queryParam(YarnWebServiceParams.CONTAINER_ID, "some text")
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
-    String responseText = response.getEntity(String.class);
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).contains(
         BadRequestException.class.getSimpleName());
     assertThat(responseText).contains("Invalid ContainerId");
@@ -792,14 +692,14 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
     ContainerId nonExistingContainerId =
         ContainerId.newContainerId(nonExistingAppAttemptId, 1);
 
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1")
         .path("history").path("containers")
         .path(nonExistingContainerId.toString()).path("logs")
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
 
-    String responseText = response.getEntity(String.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).contains(
         WebApplicationException.class.getSimpleName());
     assertThat(responseText).contains("Can not find");
@@ -807,14 +707,14 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
 
   @Test
   public void testBadContainerForMeta() {
-    WebResource r = resource();
-    ClientResponse response = r.path("ws").path("v1")
+    WebTarget r = target();
+    Response response = r.path("ws").path("v1")
         .path("history").path("containers")
         .path("some text").path("logs")
-        .accept(MediaType.APPLICATION_JSON)
-        .get(ClientResponse.class);
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
 
-    String responseText = response.getEntity(String.class);
+    String responseText = response.readEntity(String.class);
     assertThat(responseText).contains(
         BadRequestException.class.getSimpleName());
     assertThat(responseText).contains("Invalid container id");
@@ -873,20 +773,4 @@ public class TestHsWebServicesLogs extends JerseyTestBase {
     }
     return null;
   }
-
-  private void createReconfiguredServlet() {
-    Configuration newConf = new YarnConfiguration();
-    newConf.setStrings(YarnConfiguration.LOG_AGGREGATION_FILE_FORMATS,
-        FILE_FORMATS);
-    newConf.setClass(String.format(
-        YarnConfiguration.LOG_AGGREGATION_FILE_CONTROLLER_FMT, "IFile"),
-        LogAggregationIndexedFileController.class,
-        LogAggregationFileController.class);
-    newConf.set(YarnConfiguration.NM_REMOTE_APP_LOG_DIR,
-        YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR);
-    newConf.set(YarnConfiguration.NM_REMOTE_APP_LOG_DIR_SUFFIX,
-        REMOTE_LOG_DIR_SUFFIX);
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule(newConf)));
-  }
 }

+ 399 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesLogsExtend.java

@@ -0,0 +1,399 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.mapreduce.v2.hs.webapp;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.mapreduce.v2.app.AppContext;
+import org.apache.hadoop.mapreduce.v2.hs.HistoryContext;
+import org.apache.hadoop.mapreduce.v2.hs.MockHistoryContext;
+import org.apache.hadoop.mapreduce.v2.hs.webapp.reader.RemoteLogPathsMessageBodyReader;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
+import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportRequest;
+import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportResponse;
+import org.apache.hadoop.yarn.api.protocolrecords.GetContainerReportRequest;
+import org.apache.hadoop.yarn.api.protocolrecords.GetContainerReportResponse;
+import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
+import org.apache.hadoop.yarn.api.records.ApplicationId;
+import org.apache.hadoop.yarn.api.records.ApplicationReport;
+import org.apache.hadoop.yarn.api.records.ContainerId;
+import org.apache.hadoop.yarn.api.records.ContainerReport;
+import org.apache.hadoop.yarn.api.records.NodeId;
+import org.apache.hadoop.yarn.api.records.Priority;
+import org.apache.hadoop.yarn.api.records.YarnApplicationState;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.logaggregation.TestContainerLogsUtils;
+import org.apache.hadoop.yarn.logaggregation.filecontroller.LogAggregationFileController;
+import org.apache.hadoop.yarn.logaggregation.filecontroller.ifile.LogAggregationIndexedFileController;
+import org.apache.hadoop.yarn.server.webapp.LogServlet;
+import org.apache.hadoop.yarn.server.webapp.YarnWebServiceParams;
+import org.apache.hadoop.yarn.server.webapp.dao.RemoteLogPathEntry;
+import org.apache.hadoop.yarn.server.webapp.dao.RemoteLogPaths;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.yarn.webapp.JerseyTestBase;
+import org.apache.hadoop.yarn.webapp.WebApp;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+
+/**
+ * We created the following aggregated log structure, and test the log
+ * related API endpoints of {@link HsWebServices}.
+ *
+ * application_1 is finished
+ *    attempt_1
+ *       container_1 finished on node_1 syslog
+ *       container_2 finished on node_1 syslog
+ *       container_3 finished on node_2 syslog
+ *    attempt_2
+ *       container_1 finished on node_1 syslog
+ *
+ * application_2 is running
+ *    attempt_1
+ *       container_1 finished on node_1 syslog
+ *    attempt_2
+ *       container_1 finished on node_1 syslog
+ *       container_2 running on node_1 syslog
+ *       container_3 running on node_2 syslog (with some already aggregated log)
+ *
+ */
+public class TestHsWebServicesLogsExtend extends JerseyTestBase {
+
+  private static Configuration conf = new YarnConfiguration();
+  private static FileSystem fs;
+
+  private static final String LOCAL_ROOT_LOG_DIR = "target/LocalLogs";
+  private static final String REMOTE_LOG_ROOT_DIR = "target/logs/";
+
+  private static final String USER = "fakeUser";
+  private static final String FILE_NAME = "syslog";
+  private static final String REMOTE_LOG_DIR_SUFFIX = "test-logs";
+  private static final String[] FILE_FORMATS = {"IFile", "TFile"};
+
+  private static final String NM_WEBADDRESS_1 = "test-nm-web-address-1:9999";
+  private static final NodeId NM_ID_1 = NodeId.newInstance("fakeHost1", 9951);
+  private static final String NM_WEBADDRESS_2 = "test-nm-web-address-2:9999";
+  private static final NodeId NM_ID_2 = NodeId.newInstance("fakeHost2", 9952);
+
+  private static final ApplicationId APPID_1 = ApplicationId.newInstance(1, 1);
+  private static final ApplicationId APPID_2 = ApplicationId.newInstance(10, 2);
+
+  private static final ApplicationAttemptId APP_ATTEMPT_1_1 =
+      ApplicationAttemptId.newInstance(APPID_1, 1);
+  private static final ApplicationAttemptId APP_ATTEMPT_1_2 =
+      ApplicationAttemptId.newInstance(APPID_1, 2);
+  private static final ApplicationAttemptId APP_ATTEMPT_2_1 =
+      ApplicationAttemptId.newInstance(APPID_2, 1);
+  private static final ApplicationAttemptId APP_ATTEMPT_2_2 =
+      ApplicationAttemptId.newInstance(APPID_2, 2);
+
+  private static final ContainerId CONTAINER_1_1_1 =
+      ContainerId.newContainerId(APP_ATTEMPT_1_1, 1);
+  private static final ContainerId CONTAINER_1_1_2 =
+      ContainerId.newContainerId(APP_ATTEMPT_1_1, 2);
+  private static final ContainerId CONTAINER_1_1_3 =
+      ContainerId.newContainerId(APP_ATTEMPT_1_1, 3);
+  private static final ContainerId CONTAINER_1_2_1 =
+      ContainerId.newContainerId(APP_ATTEMPT_1_2, 1);
+  private static final ContainerId CONTAINER_2_1_1 =
+      ContainerId.newContainerId(APP_ATTEMPT_2_1, 1);
+  private static final ContainerId CONTAINER_2_2_1 =
+      ContainerId.newContainerId(APP_ATTEMPT_2_2, 1);
+  private static final ContainerId CONTAINER_2_2_2 =
+      ContainerId.newContainerId(APP_ATTEMPT_2_2, 2);
+  private static final ContainerId CONTAINER_2_2_3 =
+      ContainerId.newContainerId(APP_ATTEMPT_2_2, 3);
+
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder(createReconfiguredServlet()));
+    config.register(HsWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
+
+  private class JerseyBinder extends AbstractBinder {
+    private Configuration newConf;
+
+    JerseyBinder(Configuration newConf) {
+      this.newConf = newConf;
+    }
+
+    @Override
+    protected void configure() {
+
+      HsWebApp webApp = mock(HsWebApp.class);
+      when(webApp.name()).thenReturn("hsmockwebapp");
+
+      MockHistoryContext appContext = new MockHistoryContext(0, 1, 2, 1);
+      webApp = mock(HsWebApp.class);
+      when(webApp.name()).thenReturn("hsmockwebapp");
+
+      ApplicationClientProtocol mockProtocol = mock(ApplicationClientProtocol.class);
+
+      try {
+        doAnswer(invocationOnMock -> {
+          GetApplicationReportRequest request = invocationOnMock.getArgument(0);
+
+          // returning the latest application attempt for each application
+          if (request.getApplicationId().equals(APPID_1)) {
+            return GetApplicationReportResponse.newInstance(
+                newApplicationReport(APPID_1, APP_ATTEMPT_1_2, false));
+          } else if (request.getApplicationId().equals(APPID_2)) {
+            return GetApplicationReportResponse.newInstance(
+                newApplicationReport(APPID_2, APP_ATTEMPT_2_2, true));
+          }
+          throw new RuntimeException("Unknown applicationId: " + request.getApplicationId());
+        }).when(mockProtocol).getApplicationReport(any());
+
+        doAnswer(invocationOnMock -> {
+          GetContainerReportRequest request = invocationOnMock.getArgument(0);
+          ContainerId cId = request.getContainerId();
+          // for running containers assign node id and NM web address
+          if (cId.equals(CONTAINER_2_2_2)) {
+            return GetContainerReportResponse.newInstance(
+                newContainerReport(cId, NM_ID_1, NM_WEBADDRESS_1));
+          } else if (cId.equals(CONTAINER_2_2_3)) {
+            return GetContainerReportResponse.newInstance(
+                newContainerReport(cId, NM_ID_2, NM_WEBADDRESS_2));
+          }
+          // for finished application don't assign node id and NM web address
+          return GetContainerReportResponse.newInstance(
+              newContainerReport(cId, null, null));
+        }).when(mockProtocol).getContainerReport(any());
+      } catch (Exception ignore) {
+        fail("Failed to setup WebServletModule class");
+      }
+
+      Configuration usedConf = newConf == null ? conf : newConf;
+      HsWebServices hsWebServices =
+          new HsWebServices(appContext, usedConf, webApp, mockProtocol);
+      try {
+        LogServlet logServlet = hsWebServices.getLogServlet();
+        logServlet = spy(logServlet);
+        doReturn(null).when(logServlet).getNMWebAddressFromRM(any());
+        doReturn(NM_WEBADDRESS_1).when(logServlet).getNMWebAddressFromRM(NM_ID_1.toString());
+        doReturn(NM_WEBADDRESS_2).when(logServlet).getNMWebAddressFromRM(NM_ID_2.toString());
+        hsWebServices.setLogServlet(logServlet);
+      } catch (Exception ignore) {
+        fail("Failed to setup WebServletModule class");
+      }
+
+      bind(webApp).to(WebApp.class).named("hsWebApp");
+      bind(appContext).to(AppContext.class);
+      bind(appContext).to(HistoryContext.class).named("ctx");
+      bind(conf).to(Configuration.class).named("conf");
+      bind(mockProtocol).to(ApplicationClientProtocol.class).named("appClient");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      bind(response).to(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(request).to(HttpServletRequest.class);
+      hsWebServices.setResponse(response);
+      bind(hsWebServices).to(HsWebServices.class);
+    }
+  }
+
+  @BeforeClass
+  public static void setupClass() throws Exception {
+    conf.setBoolean(YarnConfiguration.LOG_AGGREGATION_ENABLED, true);
+    conf.set(YarnConfiguration.NM_REMOTE_APP_LOG_DIR, REMOTE_LOG_ROOT_DIR);
+    fs = FileSystem.get(conf);
+    createAggregatedFolders();
+  }
+
+  /**
+   * Generating aggregated container logs for all containers
+   * except CONTAINER_2_2_2, which is still running.
+   *
+   * @throws Exception if failed to create aggregated log files
+   */
+  private static void createAggregatedFolders() throws Exception {
+    Map<ContainerId, String> contentsApp1 = new HashMap<>();
+    contentsApp1.put(CONTAINER_1_1_1, "Hello-" + CONTAINER_1_1_1);
+    contentsApp1.put(CONTAINER_1_1_2, "Hello-" + CONTAINER_1_1_2);
+    contentsApp1.put(CONTAINER_1_2_1, "Hello-" + CONTAINER_1_2_1);
+
+    TestContainerLogsUtils.createContainerLogFileInRemoteFS(conf, fs,
+        LOCAL_ROOT_LOG_DIR, APPID_1, contentsApp1, NM_ID_1, FILE_NAME,
+        USER, false);
+
+    TestContainerLogsUtils.createContainerLogFileInRemoteFS(conf, fs,
+        LOCAL_ROOT_LOG_DIR, APPID_1, Collections.singletonMap(CONTAINER_1_1_3,
+        "Hello-" + CONTAINER_1_1_3), NM_ID_2, FILE_NAME, USER, false);
+
+    Map<ContainerId, String> contentsApp2 = new HashMap<>();
+    contentsApp2.put(CONTAINER_2_1_1, "Hello-" + CONTAINER_2_1_1);
+    contentsApp2.put(CONTAINER_2_2_1, "Hello-" + CONTAINER_2_2_1);
+
+    TestContainerLogsUtils.createContainerLogFileInRemoteFS(conf, fs,
+        LOCAL_ROOT_LOG_DIR, APPID_2, contentsApp2, NM_ID_1, FILE_NAME,
+        USER, false);
+
+    TestContainerLogsUtils.createContainerLogFileInRemoteFS(conf, fs,
+        LOCAL_ROOT_LOG_DIR, APPID_2, Collections.singletonMap(CONTAINER_2_2_3,
+        "Hello-" + CONTAINER_2_2_3), NM_ID_2, FILE_NAME, USER, false);
+  }
+
+  @AfterClass
+  public static void tearDownClass() throws Exception {
+    fs.delete(new Path(REMOTE_LOG_ROOT_DIR), true);
+    fs.delete(new Path(LOCAL_ROOT_LOG_DIR), true);
+  }
+
+  @Test
+  public void testRemoteLogDirWithUser() {
+    createReconfiguredServlet();
+
+    WebTarget r = target().register(RemoteLogPathsMessageBodyReader.class);
+
+    Response response = r.path("ws").path("v1").path("history")
+        .path("remote-log-dir").queryParam(YarnWebServiceParams.REMOTE_USER, USER)
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+
+    RemoteLogPaths res = response.readEntity(RemoteLogPaths.class);
+
+    List<String> collectedControllerNames = new ArrayList<>();
+    for (RemoteLogPathEntry entry: res.getPaths()) {
+      String path = String.format("%s/%s/bucket-%s-%s",
+          YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR, USER,
+          REMOTE_LOG_DIR_SUFFIX, entry.getFileController().toLowerCase());
+      collectedControllerNames.add(entry.getFileController());
+      assertEquals(entry.getPath(), path);
+    }
+
+    assertTrue(collectedControllerNames.containsAll(
+        Arrays.asList(FILE_FORMATS)));
+  }
+
+  @Test
+  public void testRemoteLogDir() {
+    createReconfiguredServlet();
+
+    UserGroupInformation ugi = UserGroupInformation.
+        createRemoteUser(USER);
+    UserGroupInformation.setLoginUser(ugi);
+
+    WebTarget r = target().register(RemoteLogPathsMessageBodyReader.class);
+    Response response = r.path("ws").path("v1").path("history")
+        .path("remote-log-dir")
+        .request(MediaType.APPLICATION_JSON).get(Response.class);
+
+    RemoteLogPaths res = response.readEntity(RemoteLogPaths.class);
+
+    List<String> collectedControllerNames = new ArrayList<>();
+    for (RemoteLogPathEntry entry: res.getPaths()) {
+      String path = String.format("%s/%s/bucket-%s-%s",
+          YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR, USER,
+          REMOTE_LOG_DIR_SUFFIX, entry.getFileController().toLowerCase());
+      collectedControllerNames.add(entry.getFileController());
+      assertEquals(entry.getPath(), path);
+    }
+
+    assertTrue(collectedControllerNames.containsAll(
+        Arrays.asList(FILE_FORMATS)));
+  }
+
+  @Test
+  public void testRemoteLogDirWithUserAndAppId() {
+    createReconfiguredServlet();
+
+    WebTarget r = target().register(RemoteLogPathsMessageBodyReader.class);
+    Response response = r.path("ws").path("v1").path("history")
+        .path("remote-log-dir")
+        .queryParam(YarnWebServiceParams.REMOTE_USER, USER)
+        .queryParam(YarnWebServiceParams.APP_ID, APPID_1.toString())
+        .request(MediaType.APPLICATION_JSON)
+        .get(Response.class);
+    RemoteLogPaths res = response.readEntity(new GenericType<RemoteLogPaths>(){});
+
+    List<String> collectedControllerNames = new ArrayList<>();
+    for (RemoteLogPathEntry entry: res.getPaths()) {
+      String path = String.format("%s/%s/bucket-%s-%s/0001/%s",
+          YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR, USER,
+          REMOTE_LOG_DIR_SUFFIX, entry.getFileController().toLowerCase(), APPID_1);
+      collectedControllerNames.add(entry.getFileController());
+      assertEquals(entry.getPath(), path);
+    }
+
+    assertTrue(collectedControllerNames.containsAll(Arrays.asList(FILE_FORMATS)));
+  }
+
+  private static ApplicationReport newApplicationReport(ApplicationId appId,
+      ApplicationAttemptId appAttemptId, boolean running) {
+    return ApplicationReport.newInstance(appId, appAttemptId, USER,
+        "fakeQueue", "fakeApplicationName", "localhost", 0, null,
+        running ? YarnApplicationState.RUNNING : YarnApplicationState.FINISHED,
+        "fake an application report", "", 1000L, 1000L, 1000L, null, null,
+        "", 50f, "fakeApplicationType", null);
+  }
+
+  private static ContainerReport newContainerReport(ContainerId containerId,
+      NodeId nodeId, String nmWebAddress) {
+    return ContainerReport.newInstance(containerId, null, nodeId,
+        Priority.UNDEFINED, 0, 0, null, null, 0, null, nmWebAddress);
+  }
+
+  private Configuration createReconfiguredServlet() {
+    Configuration newConf = new YarnConfiguration();
+    newConf.setStrings(YarnConfiguration.LOG_AGGREGATION_FILE_FORMATS,
+        FILE_FORMATS);
+    newConf.setClass(String.format(
+        YarnConfiguration.LOG_AGGREGATION_FILE_CONTROLLER_FMT, "IFile"),
+        LogAggregationIndexedFileController.class,
+        LogAggregationFileController.class);
+    newConf.set(YarnConfiguration.NM_REMOTE_APP_LOG_DIR,
+        YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR);
+    newConf.set(YarnConfiguration.NM_REMOTE_APP_LOG_DIR_SUFFIX,
+        REMOTE_LOG_DIR_SUFFIX);
+    return newConf;
+  }
+}

+ 217 - 229
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesTasks.java

@@ -22,18 +22,23 @@ import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.assertResponseS
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.io.StringReader;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
-import com.google.inject.util.Providers;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.http.JettyUtils;
 import org.apache.hadoop.mapreduce.TaskID;
@@ -49,28 +54,21 @@ import org.apache.hadoop.mapreduce.v2.util.MRApps;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.apache.hadoop.yarn.webapp.GuiceServletConfig;
 import org.apache.hadoop.yarn.webapp.JerseyTestBase;
 import org.apache.hadoop.yarn.webapp.WebApp;
 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
-import com.google.inject.Guice;
-import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.api.client.UniformInterfaceException;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import com.sun.jersey.test.framework.WebAppDescriptor;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.jettison.JettisonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
 
 /**
  * Test the history server Rest API for getting tasks, a specific task,
@@ -85,60 +83,50 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
   private static Configuration conf = new Configuration();
   private static MockHistoryContext appContext;
   private static HsWebApp webApp;
+  private static ApplicationClientProtocol acp = mock(ApplicationClientProtocol.class);
 
-  private static class WebServletModule extends ServletModule {
+  @Override
+  protected Application configure() {
+    ResourceConfig config = new ResourceConfig();
+    config.register(new JerseyBinder());
+    config.register(HsWebServices.class);
+    config.register(GenericExceptionHandler.class);
+    config.register(new JettisonFeature()).register(JAXBContextResolver.class);
+    return config;
+  }
+
+  private static class JerseyBinder extends AbstractBinder {
     @Override
-    protected void configureServlets() {
+    protected void configure() {
       appContext = new MockHistoryContext(0, 1, 2, 1);
       webApp = mock(HsWebApp.class);
       when(webApp.name()).thenReturn("hsmockwebapp");
 
-      bind(JAXBContextResolver.class);
-      bind(HsWebServices.class);
-      bind(GenericExceptionHandler.class);
-      bind(WebApp.class).toInstance(webApp);
-      bind(AppContext.class).toInstance(appContext);
-      bind(HistoryContext.class).toInstance(appContext);
-      bind(Configuration.class).toInstance(conf);
-      bind(ApplicationClientProtocol.class).toProvider(Providers.of(null));
-
-      serve("/*").with(GuiceContainer.class);
+      bind(webApp).to(WebApp.class).named("hsWebApp");
+      bind(appContext).to(AppContext.class);
+      bind(appContext).to(HistoryContext.class).named("ctx");
+      bind(conf).to(Configuration.class).named("conf");
+      bind(acp).to(ApplicationClientProtocol.class).named("appClient");
+      final HttpServletResponse response = mock(HttpServletResponse.class);
+      bind(response).to(HttpServletResponse.class);
+      final HttpServletRequest request = mock(HttpServletRequest.class);
+      bind(request).to(HttpServletRequest.class);
     }
   }
 
-  static {
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  @Before
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    GuiceServletConfig.setInjector(
-        Guice.createInjector(new WebServletModule()));
-  }
-
-  public TestHsWebServicesTasks() {
-    super(new WebAppDescriptor.Builder(
-        "org.apache.hadoop.mapreduce.v2.hs.webapp")
-        .contextListenerClass(GuiceServletConfig.class)
-        .filterClass(com.google.inject.servlet.GuiceFilter.class)
-        .contextPath("jersey-guice-filter").servletPath("/").build());
-  }
-
   @Test
   public void testTasks() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("tasks")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
       JSONArray arr = tasks.getJSONArray("task");
@@ -150,16 +138,16 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("tasks")
-          .get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request().get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
       JSONArray arr = tasks.getJSONArray("task");
@@ -171,16 +159,16 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("tasks/")
-          .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .request(MediaType.APPLICATION_JSON).get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json =response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
       JSONArray arr = tasks.getJSONArray("task");
@@ -193,16 +181,16 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
   @Test
   public void testTasksXML() throws JSONException, Exception {
 
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("tasks")
-          .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      String xml = response.getEntity(String.class);
+          .request(MediaType.APPLICATION_XML).get(Response.class);
+      assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      String xml = response.readEntity(String.class);
       DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
       DocumentBuilder db = dbf.newDocumentBuilder();
       InputSource is = new InputSource();
@@ -217,21 +205,23 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksQueryMap() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String type = "m";
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("tasks")
-          .queryParam("type", type).accept(MediaType.APPLICATION_JSON)
-          .get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .queryParam("type", type).request(MediaType.APPLICATION_JSON)
+          .get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
-      JSONArray arr = tasks.getJSONArray("task");
+      JSONObject task = tasks.getJSONObject("task");
+      JSONArray arr = new JSONArray();
+      arr.put(task);
       assertEquals("incorrect number of elements", 1, arr.length());
       verifyHsTask(arr, jobsMap.get(id), type);
     }
@@ -239,21 +229,23 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksQueryReduce() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String type = "r";
-      ClientResponse response = r.path("ws").path("v1").path("history")
+      Response response = r.path("ws").path("v1").path("history")
           .path("mapreduce").path("jobs").path(jobId).path("tasks")
-          .queryParam("type", type).accept(MediaType.APPLICATION_JSON)
-          .get(ClientResponse.class);
-      assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-          response.getType().toString());
-      JSONObject json = response.getEntity(JSONObject.class);
+          .queryParam("type", type).request(MediaType.APPLICATION_JSON)
+          .get(Response.class);
+      assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+          response.getMediaType().toString());
+      JSONObject json = response.readEntity(JSONObject.class);
       assertEquals("incorrect number of elements", 1, json.length());
       JSONObject tasks = json.getJSONObject("tasks");
-      JSONArray arr = tasks.getJSONArray("task");
+      JSONObject task = tasks.getJSONObject("task");
+      JSONArray arr = new JSONArray();
+      arr.put(task);
       assertEquals("incorrect number of elements", 1, arr.length());
       verifyHsTask(arr, jobsMap.get(id), type);
     }
@@ -261,7 +253,7 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTasksQueryInvalid() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
@@ -269,23 +261,23 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
       String tasktype = "reduce";
 
       try {
-        r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+        Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
             .path(jobId).path("tasks").queryParam("type", tasktype)
-            .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON).get();
+        throw new BadRequestException(response);
+      } catch (BadRequestException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.BAD_REQUEST, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringMatch("exception message",
-            "java.lang.Exception: tasktype must be either m or r", message);
+            "tasktype must be either m or r", message);
         WebServicesTestUtils.checkStringMatch("exception type",
             "BadRequestException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
@@ -296,19 +288,20 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskId() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .request(MediaType.APPLICATION_JSON)
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("task");
         verifyHsSingleTask(info, task);
@@ -318,20 +311,20 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdSlash() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks")
-            .path(tid + "/").accept(MediaType.APPLICATION_JSON)
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .path(tid + "/").request(MediaType.APPLICATION_JSON)
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("task");
         verifyHsSingleTask(info, task);
@@ -340,20 +333,20 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
   }
 
   @Test
-  public void testTaskIdDefault() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testTaskIdDefault() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
-            .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("history")
+            .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid).request()
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("task");
         verifyHsSingleTask(info, task);
@@ -363,33 +356,32 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdBogus() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "bogustaskid";
       try {
-        r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-            .path(jobId).path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+            .path(jobId).path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringEqual("exception message",
-            "java.lang.Exception: TaskId string : "
-                + "bogustaskid is not properly formed"
-                + "\nReason: java.util.regex.Matcher[pattern=" +
-                TaskID.TASK_ID_REGEX + " region=0,11 lastmatch=]", message);
-        WebServicesTestUtils.checkStringMatch("exception type",
-            "NotFoundException", type);
+            "TaskId string : " +
+            "bogustaskid is not properly formed" +
+            "\nReason: java.util.regex.Matcher[pattern=" +
+            TaskID.TASK_ID_REGEX + " region=0,11 lastmatch=]", message);
+        WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
             "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
       }
@@ -398,31 +390,29 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdNonExist() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "task_0_0000_m_000000";
       try {
-        r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-            .path(jobId).path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+            .path(jobId).path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringMatch("exception message",
-            "java.lang.Exception: task not found with id task_0_0000_m_000000",
-            message);
-        WebServicesTestUtils.checkStringMatch("exception type",
-            "NotFoundException", type);
+            "task not found with id task_0_0000_m_000000", message);
+        WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
             "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
       }
@@ -431,33 +421,32 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdInvalid() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "task_0_0000_d_000000";
       try {
-        r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-            .path(jobId).path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+            .path(jobId).path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringEqual("exception message",
-            "java.lang.Exception: TaskId string : "
-                + "task_0_0000_d_000000 is not properly formed" +
-                "\nReason: java.util.regex.Matcher[pattern=" +
-                TaskID.TASK_ID_REGEX + " region=0,20 lastmatch=]", message);
-        WebServicesTestUtils.checkStringMatch("exception type",
-            "NotFoundException", type);
+            "TaskId string : " +
+            "task_0_0000_d_000000 is not properly formed" +
+            "\nReason: java.util.regex.Matcher[pattern=" +
+            TaskID.TASK_ID_REGEX + " region=0,20 lastmatch=]", message);
+        WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
             "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
       }
@@ -466,33 +455,32 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdInvalid2() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "task_0000_m_000000";
       try {
-        r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-            .path(jobId).path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+            .path(jobId).path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringEqual("exception message",
-            "java.lang.Exception: TaskId string : "
-                + "task_0000_m_000000 is not properly formed" +
-                "\nReason: java.util.regex.Matcher[pattern=" +
-                TaskID.TASK_ID_REGEX + " region=0,18 lastmatch=]", message);
-        WebServicesTestUtils.checkStringMatch("exception type",
-            "NotFoundException", type);
+            "TaskId string : " +
+            "task_0000_m_000000 is not properly formed" +
+            "\nReason: java.util.regex.Matcher[pattern=" +
+            TaskID.TASK_ID_REGEX + " region=0,18 lastmatch=]", message);
+        WebServicesTestUtils.checkStringMatch("exception type", "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
             "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
       }
@@ -501,31 +489,31 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdInvalid3() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       String tid = "task_0_0000_m";
       try {
-        r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
-            .path(jobId).path("tasks").path(tid).get(JSONObject.class);
-        fail("should have thrown exception on invalid uri");
-      } catch (UniformInterfaceException ue) {
-        ClientResponse response = ue.getResponse();
-        assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo());
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject msg = response.getEntity(JSONObject.class);
+        Response response = r.path("ws").path("v1").path("history").path("mapreduce").path("jobs")
+            .path(jobId).path("tasks").path(tid).request().get();
+        throw new NotFoundException(response);
+      } catch (NotFoundException ue) {
+        Response response = ue.getResponse();
+        assertResponseStatusCode(Response.Status.NOT_FOUND, response.getStatusInfo());
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject msg = response.readEntity(JSONObject.class);
         JSONObject exception = msg.getJSONObject("RemoteException");
         assertEquals("incorrect number of elements", 3, exception.length());
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         WebServicesTestUtils.checkStringEqual("exception message",
-            "java.lang.Exception: TaskId string : "
-                + "task_0_0000_m is not properly formed" +
-                "\nReason: java.util.regex.Matcher[pattern=" +
-                TaskID.TASK_ID_REGEX + " region=0,13 lastmatch=]", message);
+            "TaskId string : " +
+            "task_0_0000_m is not properly formed" +
+            "\nReason: java.util.regex.Matcher[pattern=" +
+            TaskID.TASK_ID_REGEX + " region=0,13 lastmatch=]", message);
         WebServicesTestUtils.checkStringMatch("exception type",
             "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
@@ -536,20 +524,20 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdXML() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+            .request(MediaType.APPLICATION_XML).get(Response.class);
 
-        assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        String xml = response.getEntity(String.class);
+        assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        String xml = response.readEntity(String.class);
         DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
         DocumentBuilder db = dbf.newDocumentBuilder();
         InputSource is = new InputSource();
@@ -579,7 +567,7 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
     for (Task task : job.getTasks().values()) {
       TaskId id = task.getID();
       String tid = MRApps.toString(id);
-      Boolean found = false;
+      boolean found = false;
       if (type != null && task.getType() == MRApps.taskType(type)) {
 
         for (int i = 0; i < arr.length(); i++) {
@@ -633,7 +621,7 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
     for (Task task : job.getTasks().values()) {
       TaskId id = task.getID();
       String tid = MRApps.toString(id);
-      Boolean found = false;
+      boolean found = false;
       for (int i = 0; i < nodes.getLength(); i++) {
         Element element = (Element) nodes.item(i);
 
@@ -648,20 +636,20 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdCounters() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .path("counters").accept(MediaType.APPLICATION_JSON)
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .path("counters").request(MediaType.APPLICATION_JSON)
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("jobTaskCounters");
         verifyHsJobTaskCounters(info, task);
@@ -670,21 +658,21 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
   }
 
   @Test
-  public void testTaskIdCountersSlash() throws JSONException, Exception {
-    WebResource r = resource();
+  public void testTaskIdCountersSlash() throws Exception {
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .path("counters/").accept(MediaType.APPLICATION_JSON)
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .path("counters/").request(MediaType.APPLICATION_JSON)
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("jobTaskCounters");
         verifyHsJobTaskCounters(info, task);
@@ -694,19 +682,19 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testTaskIdCountersDefault() throws JSONException, Exception {
-    WebResource r = resource();
+    WebTarget r = targetWithJsonObject();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .path("counters").get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        JSONObject json = response.getEntity(JSONObject.class);
+            .path("counters").request().get(Response.class);
+        assertEquals(MediaType.APPLICATION_JSON_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        JSONObject json = response.readEntity(JSONObject.class);
         assertEquals("incorrect number of elements", 1, json.length());
         JSONObject info = json.getJSONObject("jobTaskCounters");
         verifyHsJobTaskCounters(info, task);
@@ -716,20 +704,20 @@ public class TestHsWebServicesTasks extends JerseyTestBase {
 
   @Test
   public void testJobTaskCountersXML() throws Exception {
-    WebResource r = resource();
+    WebTarget r = target();
     Map<JobId, Job> jobsMap = appContext.getAllJobs();
     for (JobId id : jobsMap.keySet()) {
       String jobId = MRApps.toString(id);
       for (Task task : jobsMap.get(id).getTasks().values()) {
 
         String tid = MRApps.toString(task.getID());
-        ClientResponse response = r.path("ws").path("v1").path("history")
+        Response response = r.path("ws").path("v1").path("history")
             .path("mapreduce").path("jobs").path(jobId).path("tasks").path(tid)
-            .path("counters").accept(MediaType.APPLICATION_XML)
-            .get(ClientResponse.class);
-        assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8,
-            response.getType().toString());
-        String xml = response.getEntity(String.class);
+            .path("counters").request(MediaType.APPLICATION_XML)
+            .get(Response.class);
+        assertEquals(MediaType.APPLICATION_XML_TYPE + ";" + JettyUtils.UTF_8,
+            response.getMediaType().toString());
+        String xml = response.readEntity(String.class);
         DocumentBuilderFactory dbf = XMLUtils.newSecureDocumentBuilderFactory();
         DocumentBuilder db = dbf.newDocumentBuilder();
         InputSource is = new InputSource();

+ 103 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/reader/ContainerLogsInfoMessageBodyReader.java

@@ -0,0 +1,103 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.mapreduce.v2.hs.webapp.reader;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.hadoop.yarn.logaggregation.ContainerLogFileInfo;
+import org.apache.hadoop.yarn.server.webapp.dao.ContainerLogsInfo;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * We have defined a custom reader for List<ContainerLogsInfo>
+ * to adapt to the Jersey2 framework, ensuring it can be converted to JSON format.
+ */
+@Provider
+@Consumes(MediaType.APPLICATION_JSON)
+public class ContainerLogsInfoMessageBodyReader
+    implements MessageBodyReader<List<ContainerLogsInfo>> {
+
+  private ObjectMapper objectMapper = new ObjectMapper();
+  private String genericTypeName =
+      "java.util.List<org.apache.hadoop.yarn.server.webapp.dao.ContainerLogsInfo>";
+
+  @Override
+  public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
+      MediaType mediaType) {
+    return type == List.class && (genericTypeName.equals(genericType.getTypeName()));
+  }
+
+  @Override
+  public List<ContainerLogsInfo> readFrom(Class<List<ContainerLogsInfo>> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+      InputStream entityStream) throws IOException, WebApplicationException {
+    JsonNode rootNode = objectMapper.readTree(entityStream);
+    JsonNode jContainerLogsInfoes = rootNode.get("containerLogsInfoes");
+    JsonNode jContainerLogsInfo = jContainerLogsInfoes.get("containerLogsInfo");
+
+    List<ContainerLogsInfo> containerLogsInfos = new ArrayList<>();
+    if (jContainerLogsInfo.isArray()) {
+      for (JsonNode containerLogsInfoItem : jContainerLogsInfo) {
+        ContainerLogsInfo containerLogsInfo = parseContainerLogsInfo(containerLogsInfoItem);
+        containerLogsInfos.add(containerLogsInfo);
+      }
+    } else {
+      ContainerLogsInfo containerLogsInfo = parseContainerLogsInfo(jContainerLogsInfo);
+      containerLogsInfos.add(containerLogsInfo);
+    }
+    return containerLogsInfos;
+  }
+
+  private ContainerLogsInfo parseContainerLogsInfo(JsonNode containerLogsInfoItem) {
+    ContainerLogsInfo containerLogsInfo = new ContainerLogsInfo();
+    List<ContainerLogFileInfo> containerLogFileInfos = new ArrayList<>();
+    JsonNode jsonNode = containerLogsInfoItem.get("containerLogInfo");
+    JsonNode logAggregationType = containerLogsInfoItem.get("logAggregationType");
+    JsonNode containerId = containerLogsInfoItem.get("containerId");
+    JsonNode nodeId = containerLogsInfoItem.get("nodeId");
+
+    if (jsonNode != null) {
+      ContainerLogFileInfo containerLogFileInfo = new ContainerLogFileInfo();
+      JsonNode fileName = jsonNode.get("fileName");
+      containerLogFileInfo.setFileName(fileName.asText());
+      JsonNode fileSize = jsonNode.get("fileSize");
+      containerLogFileInfo.setFileSize(fileSize.asText());
+      JsonNode lastModifiedTime = jsonNode.get("lastModifiedTime");
+      containerLogFileInfo.setLastModifiedTime(lastModifiedTime.asText());
+      containerLogFileInfos.add(containerLogFileInfo);
+      containerLogsInfo.setContainerLogsInfo(containerLogFileInfos);
+    }
+
+    containerLogsInfo.setContainerId(containerId.asText());
+    containerLogsInfo.setNodeId(nodeId.asText());
+    containerLogsInfo.setLogType(logAggregationType.asText());
+    return containerLogsInfo;
+  }
+}

+ 88 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/reader/RemoteLogPathsMessageBodyReader.java

@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.mapreduce.v2.hs.webapp.reader;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.hadoop.yarn.server.webapp.dao.RemoteLogPathEntry;
+import org.apache.hadoop.yarn.server.webapp.dao.RemoteLogPaths;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * We have defined a custom reader for RemoteLogPaths
+ * to adapt to the Jersey2 framework, ensuring it can be converted to JSON format.
+ */
+@Provider
+@Consumes(MediaType.APPLICATION_JSON)
+public class RemoteLogPathsMessageBodyReader implements MessageBodyReader<RemoteLogPaths> {
+
+  private ObjectMapper objectMapper = new ObjectMapper();
+
+  @Override
+  public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
+      MediaType mediaType) {
+    return RemoteLogPaths.class.isAssignableFrom(type);
+  }
+
+  @Override
+  public RemoteLogPaths readFrom(Class<RemoteLogPaths> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+      InputStream entityStream) throws IOException, WebApplicationException {
+
+    JsonNode rootNode = objectMapper.readTree(entityStream);
+    List<RemoteLogPathEntry> pathEntries = new ArrayList<>();
+
+    JsonNode jsonNode = rootNode.get("remoteLogDirPathResult");
+    JsonNode paths = jsonNode.get("paths");
+
+    if (paths.isObject()) {
+      RemoteLogPathEntry entry = parseRemoteLogPathEntry(paths);
+      pathEntries.add(entry);
+    }
+
+    if (paths.isArray()) {
+      for (JsonNode path : paths) {
+        RemoteLogPathEntry entry = parseRemoteLogPathEntry(path);
+        pathEntries.add(entry);
+      }
+    }
+
+    return new RemoteLogPaths(pathEntries);
+  }
+
+  private RemoteLogPathEntry parseRemoteLogPathEntry(JsonNode paths) {
+    RemoteLogPathEntry entry = new RemoteLogPathEntry();
+    JsonNode fileController = paths.get("fileController");
+    JsonNode path = paths.get("path");
+    entry.setPath(path.asText());
+    entry.setFileController(fileController.asText());
+    return entry;
+  }
+}

+ 21 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/pom.xml

@@ -128,6 +128,27 @@
       <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
  <profiles>

+ 20 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-nativetask/pom.xml

@@ -60,6 +60,26 @@
       <artifactId>lz4-java</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 5 - 0
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-shuffle/pom.xml

@@ -61,6 +61,11 @@
       <version>1.1.2</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 7 - 2
hadoop-mapreduce-project/hadoop-mapreduce-client/pom.xml

@@ -156,8 +156,13 @@
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey.jersey-test-framework</groupId>
-      <artifactId>jersey-test-framework-grizzly2</artifactId>
+      <groupId>org.glassfish.jersey.test-framework</groupId>
+      <artifactId>jersey-test-framework-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+      <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>

+ 7 - 2
hadoop-mapreduce-project/hadoop-mapreduce-examples/pom.xml

@@ -95,8 +95,13 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>com.sun.jersey.jersey-test-framework</groupId>
-      <artifactId>jersey-test-framework-grizzly2</artifactId>
+      <groupId>org.glassfish.jersey.test-framework</groupId>
+      <artifactId>jersey-test-framework-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+      <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>

+ 79 - 110
hadoop-project/pom.xml

@@ -66,7 +66,7 @@
     <avro.version>1.11.4</avro.version>
 
     <!-- jersey version -->
-    <jersey.version>1.19.4</jersey.version>
+    <jersey2.version>2.46</jersey2.version>
 
     <!-- jackson versions -->
     <jackson2.version>2.12.7</jackson2.version>
@@ -851,14 +851,9 @@
         <version>${commons-net.version}</version>
       </dependency>
       <dependency>
-        <groupId>javax.servlet</groupId>
-        <artifactId>javax.servlet-api</artifactId>
-        <version>3.1.0</version>
-      </dependency>
-      <dependency>
-        <groupId>javax.ws.rs</groupId>
-        <artifactId>jsr311-api</artifactId>
-        <version>1.1.1</version>
+        <groupId>jakarta.ws.rs</groupId>
+        <artifactId>jakarta.ws.rs-api</artifactId>
+        <version>2.1.6</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.jetty</groupId>
@@ -912,14 +907,14 @@
         <version>${jetty.version}</version>
       </dependency>
       <dependency>
-        <groupId>javax.servlet.jsp</groupId>
-        <artifactId>jsp-api</artifactId>
-        <version>2.1</version>
+        <groupId>jakarta.servlet.jsp</groupId>
+        <artifactId>jakarta.servlet.jsp-api</artifactId>
+        <version>2.3.6</version>
       </dependency>
       <dependency>
-        <groupId>org.glassfish</groupId>
-        <artifactId>javax.servlet</artifactId>
-        <version>3.1</version>
+        <groupId>jakarta.servlet</groupId>
+        <artifactId>jakarta.servlet-api</artifactId>
+        <version>4.0.4</version>
       </dependency>
 
       <dependency>
@@ -943,50 +938,6 @@
           <artifactId>ojalgo</artifactId>
           <version>43.0</version>
       </dependency>
-      <dependency>
-        <groupId>com.sun.jersey</groupId>
-        <artifactId>jersey-core</artifactId>
-        <version>${jersey.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-      <dependency>
-        <groupId>com.sun.jersey</groupId>
-        <artifactId>jersey-servlet</artifactId>
-        <version>${jersey.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>com.github.pjfanning</groupId>
-        <artifactId>jersey-json</artifactId>
-        <version>1.22.0</version>
-        <exclusions>
-          <exclusion>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-core</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>com.fasterxml.jackson.jaxrs</groupId>
-            <artifactId>jackson-jaxrs-json-provider</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>org.codehaus.jettison</groupId>
-            <artifactId>jettison</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-      <dependency>
-        <groupId>com.sun.jersey</groupId>
-        <artifactId>jersey-server</artifactId>
-        <version>${jersey.version}</version>
-      </dependency>
 
       <dependency>
         <groupId>com.google.inject</groupId>
@@ -1006,36 +957,6 @@
         <version>${guice.version}</version>
       </dependency>
 
-      <dependency>
-        <groupId>com.sun.jersey.contribs</groupId>
-        <artifactId>jersey-guice</artifactId>
-        <version>${jersey.version}</version>
-      </dependency>
-
-      <dependency>
-        <groupId>com.sun.jersey.jersey-test-framework</groupId>
-        <artifactId>jersey-test-framework-core</artifactId>
-        <version>${jersey.version}</version>
-        <scope>test</scope>
-        <exclusions>
-          <exclusion>
-            <groupId>javax.servlet</groupId>
-            <artifactId>javax.servlet-api</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-      <dependency>
-        <groupId>com.sun.jersey.jersey-test-framework</groupId>
-        <artifactId>jersey-test-framework-grizzly2</artifactId>
-        <version>${jersey.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>javax.servlet</groupId>
-            <artifactId>javax.servlet-api</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-
       <dependency>
         <groupId>io.netty</groupId>
         <artifactId>netty-all</artifactId>
@@ -1598,9 +1519,9 @@
         <version>3.0.2</version>
       </dependency>
       <dependency>
-        <groupId>javax.xml.bind</groupId>
-        <artifactId>jaxb-api</artifactId>
-        <version>2.2.11</version>
+        <groupId>jakarta.xml.bind</groupId>
+        <artifactId>jakarta.xml.bind-api</artifactId>
+        <version>2.3.3</version>
       </dependency>
       <dependency>
         <groupId>org.codehaus.jettison</groupId>
@@ -1613,11 +1534,6 @@
           </exclusion>
         </exclusions>
       </dependency>
-      <dependency>
-        <groupId>com.sun.jersey</groupId>
-        <artifactId>jersey-client</artifactId>
-        <version>${jersey.version}</version>
-      </dependency>
 
       <dependency>
         <groupId>${leveldbjni.group}</groupId>
@@ -2110,6 +2026,10 @@
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
           </exclusion>
+          <exclusion>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+          </exclusion>
         </exclusions>
       </dependency>
       <dependency>
@@ -2147,6 +2067,68 @@
         <artifactId>cache-api</artifactId>
         <version>${cache.api.version}</version>
       </dependency>
+      <!-- jersey2 -->
+      <dependency>
+        <groupId>org.glassfish.jersey.containers</groupId>
+        <artifactId>jersey-container-servlet-core</artifactId>
+        <version>${jersey2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.containers</groupId>
+        <artifactId>jersey-container-servlet</artifactId>
+        <version>${jersey2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.core</groupId>
+        <artifactId>jersey-client</artifactId>
+        <version>${jersey2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.core</groupId>
+        <artifactId>jersey-common</artifactId>
+        <version>${jersey2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.core</groupId>
+        <artifactId>jersey-server</artifactId>
+        <version>${jersey2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.media</groupId>
+        <artifactId>jersey-media-jaxb</artifactId>
+        <version>${jersey2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.inject</groupId>
+        <artifactId>jersey-hk2</artifactId>
+        <version>${jersey2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.test-framework</groupId>
+        <artifactId>jersey-test-framework-core</artifactId>
+        <version>${jersey2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+        <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+        <version>${jersey2.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.media</groupId>
+        <artifactId>jersey-media-json-jettison</artifactId>
+        <version>${jersey2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>net.jodah</groupId>
+        <artifactId>failsafe</artifactId>
+        <version>2.4.4</version>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
@@ -2542,9 +2524,6 @@
                 <bannedDependencies>
                   <excludes>
                     <exclude>cglib:cglib:</exclude>
-                    <exclude>com.sun.jersey:*</exclude>
-                    <exclude>com.sun.jersey.contribs:*</exclude>
-                    <exclude>com.sun.jersey.jersey-test-framework:*</exclude>
                     <exclude>com.google.inject:guice</exclude>
                     <exclude>org.ow2.asm:asm</exclude>
 
@@ -2556,16 +2535,6 @@
                     <!-- for JDK 8 support -->
                     <include>cglib:cglib:3.2.0</include>
                     <include>com.google.inject:guice:5.1.0</include>
-                    <include>com.sun.jersey:jersey-core:1.19.4</include>
-                    <include>com.sun.jersey:jersey-servlet:1.19.4</include>
-                    <include>com.github.pjfanning:jersey-json:1.22.0</include>
-                    <include>com.sun.jersey:jersey-server:1.19.4</include>
-                    <include>com.sun.jersey:jersey-client:1.19.4</include>
-                    <include>com.sun.jersey:jersey-grizzly2:1.19.4</include>
-                    <include>com.sun.jersey:jersey-grizzly2-servlet:1.19.4</include>
-                    <include>com.sun.jersey.jersey-test-framework:jersey-test-framework-core:1.19.4</include>
-                    <include>com.sun.jersey.jersey-test-framework:jersey-test-framework-grizzly2:1.19.4</include>
-                    <include>com.sun.jersey.contribs:jersey-guice:1.19.4</include>
                     <include>org.ow2.asm:asm:5.0.0</include>
                   </includes>
                 </bannedDependencies>

+ 20 - 0
hadoop-tools/hadoop-archive-logs/pom.xml

@@ -142,6 +142,26 @@
       <scope>test</scope>
       <type>test-jar</type>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 20 - 0
hadoop-tools/hadoop-archives/pom.xml

@@ -103,6 +103,26 @@
       <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 20 - 0
hadoop-tools/hadoop-aws/pom.xml

@@ -581,5 +581,25 @@
       <artifactId>bcpkix-jdk18on</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>

+ 21 - 0
hadoop-tools/hadoop-azure-datalake/pom.xml

@@ -176,5 +176,26 @@
       <scope>compile</scope>
     </dependency>
 
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 </project>

+ 22 - 3
hadoop-tools/hadoop-azure/pom.xml

@@ -315,8 +315,8 @@
     </dependency>
 
     <dependency>
-      <groupId>javax.ws.rs</groupId>
-      <artifactId>jsr311-api</artifactId>
+      <groupId>jakarta.ws.rs</groupId>
+      <artifactId>jakarta.ws.rs-api</artifactId>
       <scope>test</scope>
     </dependency>
 
@@ -352,7 +352,26 @@
       <artifactId>hamcrest-library</artifactId>
       <scope>test</scope>
     </dependency>
-
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <profiles>

+ 20 - 0
hadoop-tools/hadoop-datajoin/pom.xml

@@ -109,6 +109,26 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 20 - 0
hadoop-tools/hadoop-distcp/pom.xml

@@ -120,6 +120,26 @@
       <version>1.3</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 20 - 0
hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-blockgen/pom.xml

@@ -49,6 +49,26 @@
       <artifactId>hadoop-minicluster</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 20 - 0
hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-infra/pom.xml

@@ -102,6 +102,26 @@
       <scope>test</scope>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 20 - 0
hadoop-tools/hadoop-dynamometer/hadoop-dynamometer-workload/pom.xml

@@ -49,6 +49,26 @@
       <artifactId>hadoop-minicluster</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 20 - 0
hadoop-tools/hadoop-extras/pom.xml

@@ -134,6 +134,26 @@
       <artifactId>bcpkix-jdk18on</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 20 - 0
hadoop-tools/hadoop-federation-balance/pom.xml

@@ -124,6 +124,26 @@
       <artifactId>hadoop-minicluster</artifactId>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

+ 20 - 0
hadoop-tools/hadoop-fs2img/pom.xml

@@ -77,6 +77,26 @@
       <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

部分文件因为文件数量过多而无法显示