This is an automated email from the ASF dual-hosted git repository.

bteke pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 2ce5d35a578 MAPREDUCE-7530. MR AM REST API backward compatibility with 
Jersey1 (#8247)
2ce5d35a578 is described below

commit 2ce5d35a578e6b5146a852bfd38f5f363fd727f1
Author: K0K0V0K <[email protected]>
AuthorDate: Thu Feb 19 15:33:50 2026 +0100

    MAPREDUCE-7530. MR AM REST API backward compatibility with Jersey1 (#8247)
---
 .../hadoop-mapreduce-client-app/pom.xml            |  4 ++
 .../mapreduce/v2/app/client/MRClientService.java   |  8 +--
 .../v2/app/webapp/JAXBContextResolver.java         | 66 ++++++------------
 .../v2/app/webapp/dao/MapTaskAttemptInfo.java      |  2 +
 .../v2/app/webapp/dao/ReduceTaskAttemptInfo.java   |  2 +
 .../v2/app/webapp/dao/TaskAttemptInfo.java         |  4 --
 .../jsonprovider/ClassSerializationConfig.java     | 80 +++++++++++++++++++++
 .../jsonprovider/ExcludeRootJSONProvider.java      | 81 ++++++++++++++++++++++
 .../jsonprovider/IncludeRootJSONProvider.java      | 80 +++++++++++++++++++++
 .../JsonProviderFeature.java}                      | 36 +++++-----
 .../package-info.java}                             | 33 +++------
 .../v2/app/webapp/TestAMWebServicesAttempts.java   |  9 +--
 12 files changed, 301 insertions(+), 104 deletions(-)

diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/pom.xml
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/pom.xml
index 198afa9c9a3..0561804e00d 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/pom.xml
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/pom.xml
@@ -148,6 +148,10 @@
       <groupId>org.glassfish.jersey.media</groupId>
       <artifactId>jersey-media-json-jettison</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.eclipse.persistence</groupId>
+      <artifactId>org.eclipse.persistence.moxy</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-api</artifactId>
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/client/MRClientService.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/client/MRClientService.java
index 8c7f4cb0bdd..052377b1942 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/client/MRClientService.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/client/MRClientService.java
@@ -81,6 +81,7 @@
 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.mapreduce.v2.app.webapp.jsonprovider.JsonProviderFeature;
 import org.apache.hadoop.net.NetUtils;
 import org.apache.hadoop.security.AccessControlException;
 import org.apache.hadoop.security.UserGroupInformation;
@@ -94,7 +95,6 @@
 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;
@@ -152,7 +152,7 @@ protected void serviceStart() throws Exception {
           MRJobConfig.MR_AM_WEBAPP_HTTPS_CLIENT_AUTH,
           MRJobConfig.DEFAULT_MR_AM_WEBAPP_HTTPS_CLIENT_AUTH);
       webApp =
-          WebApps.$for("mapreduce", AppContext.class, appContext, "ws")
+          WebApps.$for("mapreduce", AppContext.class, appContext, "rm-ws")
             .withHttpPolicy(conf, httpPolicy)
             .withPortRange(conf, MRJobConfig.MR_AM_WEBAPP_PORT_RANGE)
             .needsClientAuth(needsClientAuth)
@@ -451,11 +451,11 @@ public WebApp getWebApp() {
 
   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);
+    config.register(JsonProviderFeature.class);
+    config.register(JAXBContextResolver.class);
     return config;
   }
 
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/JAXBContextResolver.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/JAXBContextResolver.java
index af1ea61ef00..8bc99652fdc 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/JAXBContextResolver.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/JAXBContextResolver.java
@@ -18,68 +18,44 @@
 
 package org.apache.hadoop.mapreduce.v2.app.webapp;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
 
-import org.glassfish.jersey.jettison.JettisonJaxbContext;
 import javax.inject.Singleton;
 
 import javax.ws.rs.ext.ContextResolver;
 import javax.ws.rs.ext.Provider;
 import javax.xml.bind.JAXBContext;
 
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.AMAttemptInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.AMAttemptsInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.AppInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.ConfInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.ConfEntryInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.CounterGroupInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.CounterInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobCounterInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobTaskAttemptState;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobsInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobTaskAttemptCounterInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobTaskCounterInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.MapTaskAttemptInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.ReduceTaskAttemptInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskAttemptsInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskCounterGroupInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskCounterInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskInfo;
-import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TasksInfo;
-import org.apache.hadoop.yarn.webapp.RemoteExceptionData;
+import 
org.apache.hadoop.mapreduce.v2.app.webapp.jsonprovider.ClassSerializationConfig;
 
 @Singleton
 @Provider
 public class JAXBContextResolver implements ContextResolver<JAXBContext> {
 
-  private final Map<Class, JAXBContext> typesContextMap;
-
-  // you have to specify all the dao classes here
-  private final Class[] cTypes = {AMAttemptInfo.class, AMAttemptsInfo.class,
-    AppInfo.class, CounterInfo.class, JobTaskAttemptCounterInfo.class,
-    JobTaskCounterInfo.class, TaskCounterGroupInfo.class, ConfInfo.class,
-    JobCounterInfo.class, TaskCounterInfo.class, CounterGroupInfo.class,
-    JobInfo.class, JobsInfo.class, MapTaskAttemptInfo.class, 
ReduceTaskAttemptInfo.class,
-    TaskInfo.class, TasksInfo.class, TaskAttemptsInfo.class, 
ConfEntryInfo.class, RemoteExceptionData.class};
-
-  // these dao classes need root unwrapping
-  private final Class[] rootUnwrappedTypes = {JobTaskAttemptState.class};
+  private final Map<Class, JAXBContext> typesContextMap = new HashMap<>();
 
   public JAXBContextResolver() throws Exception {
-    JAXBContext context;
-    JAXBContext unWrappedRootContext;
+    ClassSerializationConfig classSerializationConfig = new 
ClassSerializationConfig();
+    Set<Class<?>> wrappedClasses = 
classSerializationConfig.getWrappedClasses();
+    Set<Class<?>> unWrappedClasses = 
classSerializationConfig.getUnWrappedClasses();
+
+    JAXBContext wrappedContext = JAXBContextFactory.createContext(
+        wrappedClasses.toArray(new Class[0]),
+        Collections.singletonMap(MarshallerProperties.JSON_INCLUDE_ROOT, true)
+    );
+    JAXBContext unWrappedContext = JAXBContextFactory.createContext(
+        unWrappedClasses.toArray(new Class[0]),
+        Collections.singletonMap(MarshallerProperties.JSON_INCLUDE_ROOT, false)
+    );
 
-    this.typesContextMap = new HashMap<>();
-    context = new JettisonJaxbContext(cTypes);
-    unWrappedRootContext = new JettisonJaxbContext(rootUnwrappedTypes);
-    for (Class type : cTypes) {
-      typesContextMap.put(type, context);
-    }
-    for (Class type : rootUnwrappedTypes) {
-      typesContextMap.put(type, unWrappedRootContext);
-    }
+    wrappedClasses.forEach(type -> typesContextMap.put(type, wrappedContext));
+    unWrappedClasses.forEach(type -> typesContextMap.put(type, 
unWrappedContext));
   }
 
   @Override
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
index bcd790a9c31..71aadbe2dde 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
@@ -22,8 +22,10 @@
 import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt;
 
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
 
 @XmlRootElement(name = "taskAttempt")
+@XmlType(name = "")
 public class MapTaskAttemptInfo extends TaskAttemptInfo {
 
   public MapTaskAttemptInfo() {
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/ReduceTaskAttemptInfo.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/ReduceTaskAttemptInfo.java
index dbc76ec9d0b..a86d068eb0f 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/ReduceTaskAttemptInfo.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/ReduceTaskAttemptInfo.java
@@ -19,12 +19,14 @@
 package org.apache.hadoop.mapreduce.v2.app.webapp.dao;
 
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
 
 import org.apache.hadoop.mapreduce.v2.api.records.TaskType;
 import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt;
 import org.apache.hadoop.yarn.util.Times;
 
 @XmlRootElement(name = "taskAttempt")
+@XmlType(name = "")
 public class ReduceTaskAttemptInfo extends TaskAttemptInfo {
 
   protected long shuffleFinishTime;
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/TaskAttemptInfo.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/TaskAttemptInfo.java
index 140202ef4c8..41db498f58a 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/TaskAttemptInfo.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/TaskAttemptInfo.java
@@ -125,8 +125,4 @@ public String getRack() {
   public String getNote() {
     return this.diagnostics;
   }
-
-  public String getType() {
-    return type;
-  }
 }
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/ClassSerializationConfig.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/ClassSerializationConfig.java
new file mode 100644
index 00000000000..2a5c216c8cd
--- /dev/null
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/ClassSerializationConfig.java
@@ -0,0 +1,80 @@
+/**
+ * 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.app.webapp.jsonprovider;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.AMAttemptInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.AMAttemptsInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.AppInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.ConfEntryInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.CounterGroupInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.CounterInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobCounterInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobTaskAttemptCounterInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobTaskAttemptState;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobTaskCounterInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.JobsInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.MapTaskAttemptInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.ReduceTaskAttemptInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskAttemptInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskAttemptsInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskCounterGroupInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskCounterInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskInfo;
+import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TasksInfo;
+import org.apache.hadoop.util.Sets;
+import org.apache.hadoop.yarn.webapp.RemoteExceptionData;
+
+public class ClassSerializationConfig {
+
+  private static final Set<Class<?>> CONST_WRAPPED_CLASSES = Sets.newHashSet(
+      AMAttemptInfo.class, AMAttemptsInfo.class,
+      AppInfo.class, CounterInfo.class, JobTaskAttemptCounterInfo.class,
+      JobTaskCounterInfo.class, TaskCounterGroupInfo.class,
+      org.apache.hadoop.mapreduce.v2.app.webapp.dao.ConfInfo.class,
+      JobCounterInfo.class, TaskCounterInfo.class, CounterGroupInfo.class,
+      JobInfo.class, JobsInfo.class, MapTaskAttemptInfo.class, 
ReduceTaskAttemptInfo.class,
+      TaskInfo.class, TasksInfo.class, TaskAttemptInfo.class, 
TaskAttemptsInfo.class,
+      ConfEntryInfo.class, RemoteExceptionData.class
+  );
+
+  private static final Set<Class<?>> CONST_UNWRAPPED_CLASSES =
+      Sets.newHashSet(JobTaskAttemptState.class);
+
+  private final Set<Class<?>> wrappedClasses;
+  private final Set<Class<?>> unWrappedClasses;
+
+
+  public ClassSerializationConfig() {
+    wrappedClasses = new HashSet<>(CONST_WRAPPED_CLASSES);
+    unWrappedClasses = new HashSet<>(CONST_UNWRAPPED_CLASSES);
+  }
+
+  public Set<Class<?>> getWrappedClasses() {
+    return wrappedClasses;
+  }
+
+  public Set<Class<?>> getUnWrappedClasses() {
+    return unWrappedClasses;
+  }
+
+}
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/ExcludeRootJSONProvider.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/ExcludeRootJSONProvider.java
new file mode 100644
index 00000000000..ad61c842cbc
--- /dev/null
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/ExcludeRootJSONProvider.java
@@ -0,0 +1,81 @@
+/**
+ * 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.app.webapp.jsonprovider;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Provider
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class ExcludeRootJSONProvider extends MOXyJsonProvider {
+
+  private final static Logger LOG = 
LoggerFactory.getLogger(ExcludeRootJSONProvider.class);
+  private final ClassSerializationConfig classSerializationConfig;
+
+  @Inject
+  public ExcludeRootJSONProvider() {
+    classSerializationConfig = new ClassSerializationConfig();
+  }
+
+  @Override
+  public boolean isReadable(Class<?> type, Type genericType, Annotation[] 
annotations,
+      MediaType mediaType) {
+    boolean match = 
classSerializationConfig.getUnWrappedClasses().contains(type);
+    LOG.trace("ExcludeRootJSONProvider compatibility with {} is {}", type, 
match);
+    return match;
+  }
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType, Annotation[] 
annotations,
+      MediaType mediaType) {
+    return isReadable(type, genericType, annotations, mediaType);
+  }
+
+  @Override
+  protected void preReadFrom(Class<Object> type, Type genericType, 
Annotation[] annotations,
+      MediaType mediaType, MultivaluedMap<String, String> httpHeaders, 
Unmarshaller unmarshaller)
+      throws JAXBException {
+    LOG.trace("ExcludeRootJSONProvider preReadFrom with {}", type);
+    unmarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
+  }
+
+  @Override
+  protected void preWriteTo(Object object, Class<?> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, 
Object> httpHeaders,
+      Marshaller marshaller) throws JAXBException {
+    LOG.trace("ExcludeRootJSONProvider preWriteTo with {}", type);
+    
marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, 
false);
+    marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
+  }
+}
\ No newline at end of file
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/IncludeRootJSONProvider.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/IncludeRootJSONProvider.java
new file mode 100644
index 00000000000..4fcece9987e
--- /dev/null
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/IncludeRootJSONProvider.java
@@ -0,0 +1,80 @@
+/**
+ * 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.app.webapp.jsonprovider;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Provider
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class IncludeRootJSONProvider extends MOXyJsonProvider {
+  private final static Logger LOG = 
LoggerFactory.getLogger(IncludeRootJSONProvider.class);
+  private final ClassSerializationConfig classSerializationConfig;
+
+  @Inject
+  public IncludeRootJSONProvider() {
+    classSerializationConfig = new ClassSerializationConfig();
+  }
+
+  @Override
+  public boolean isReadable(Class<?> type, Type genericType, Annotation[] 
annotations,
+      MediaType mediaType) {
+    boolean match = 
classSerializationConfig.getWrappedClasses().contains(type);
+    LOG.trace("IncludeRootJSONProvider compatibility with {} is {}", type, 
match);
+    return match;
+  }
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType, Annotation[] 
annotations,
+      MediaType mediaType) {
+    return isReadable(type, genericType, annotations, mediaType);
+  }
+
+  @Override
+  protected void preReadFrom(Class<Object> type, Type genericType, 
Annotation[] annotations,
+      MediaType mediaType, MultivaluedMap<String, String> httpHeaders, 
Unmarshaller unmarshaller)
+      throws JAXBException {
+    LOG.trace("IncludeRootJSONProvider preReadFrom with {}", type);
+    unmarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
+  }
+
+  @Override
+  protected void preWriteTo(Object object, Class<?> type, Type genericType,
+      Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, 
Object> httpHeaders,
+      Marshaller marshaller) throws JAXBException {
+    LOG.trace("IncludeRootJSONProvider preWriteTo with {}", type);
+    
marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, 
false);
+    marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
+  }
+}
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/JsonProviderFeature.java
similarity index 53%
copy from 
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
copy to 
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/JsonProviderFeature.java
index bcd790a9c31..fdc73cbf876 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/JsonProviderFeature.java
@@ -6,9 +6,9 @@
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *     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.
@@ -16,24 +16,20 @@
  * limitations under the License.
  */
 
-package org.apache.hadoop.mapreduce.v2.app.webapp.dao;
+package org.apache.hadoop.mapreduce.v2.app.webapp.jsonprovider;
 
-import org.apache.hadoop.mapreduce.v2.api.records.TaskType;
-import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
 
-import javax.xml.bind.annotation.XmlRootElement;
+import org.glassfish.jersey.CommonProperties;
 
-@XmlRootElement(name = "taskAttempt")
-public class MapTaskAttemptInfo extends TaskAttemptInfo {
-
-  public MapTaskAttemptInfo() {
-  }
-
-  public MapTaskAttemptInfo(TaskAttempt ta) {
-    this(ta, false);
-  }
-
-  public MapTaskAttemptInfo(TaskAttempt ta, Boolean isRunning) {
-    super(ta, TaskType.MAP, isRunning);
+public class JsonProviderFeature implements Feature {
+  @Override
+  public boolean configure(FeatureContext context) {
+    //Auto discovery should be disabled to ensure the custom providers will be 
used
+    context.property(CommonProperties.MOXY_JSON_FEATURE_DISABLE, true);
+    context.register(IncludeRootJSONProvider.class, 2001);
+    context.register(ExcludeRootJSONProvider.class, 2002);
+    return true;
   }
-}
\ No newline at end of file
+}
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/package-info.java
similarity index 55%
copy from 
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
copy to 
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/package-info.java
index bcd790a9c31..f1aa7642a6c 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/dao/MapTaskAttemptInfo.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/jsonprovider/package-info.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -6,9 +6,9 @@
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *     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.
@@ -16,24 +16,7 @@
  * limitations under the License.
  */
 
-package org.apache.hadoop.mapreduce.v2.app.webapp.dao;
-
-import org.apache.hadoop.mapreduce.v2.api.records.TaskType;
-import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt;
-
-import javax.xml.bind.annotation.XmlRootElement;
-
-@XmlRootElement(name = "taskAttempt")
-public class MapTaskAttemptInfo extends TaskAttemptInfo {
-
-  public MapTaskAttemptInfo() {
-  }
-
-  public MapTaskAttemptInfo(TaskAttempt ta) {
-    this(ta, false);
-  }
-
-  public MapTaskAttemptInfo(TaskAttempt ta, Boolean isRunning) {
-    super(ta, TaskType.MAP, isRunning);
-  }
-}
\ No newline at end of file
+/**
+ * Jersey2 JSON provider classes for the MapReduce Application web UI.
+ */
+package org.apache.hadoop.mapreduce.v2.app.webapp.jsonprovider;
\ No newline at end of file
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesAttempts.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesAttempts.java
index 2a3e13f3c0c..67b2809ac7f 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesAttempts.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/webapp/TestAMWebServicesAttempts.java
@@ -51,6 +51,7 @@
 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.job.TaskAttempt;
+import 
org.apache.hadoop.mapreduce.v2.app.webapp.jsonprovider.JsonProviderFeature;
 import org.apache.hadoop.mapreduce.v2.util.MRApps;
 import org.apache.hadoop.util.XMLUtils;
 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
@@ -66,7 +67,6 @@
 import org.xml.sax.InputSource;
 
 import org.glassfish.jersey.internal.inject.AbstractBinder;
-import org.glassfish.jersey.jettison.JettisonFeature;
 import org.glassfish.jersey.server.ResourceConfig;
 
 /**
@@ -88,7 +88,7 @@ protected Application configure() {
     config.register(new JerseyBinder());
     config.register(AMWebServices.class);
     config.register(GenericExceptionHandler.class);
-    config.register(new JettisonFeature());
+    config.register(JsonProviderFeature.class);
     config.register(JAXBContextResolver.class);
     return config;
   }
@@ -449,10 +449,7 @@ public void verifyAMTaskAttempts(JSONObject json, Task 
task)
       throws JSONException {
     assertEquals(1, json.length(), "incorrect number of elements");
     JSONObject attempts = json.getJSONObject("taskAttempts");
-    assertEquals(1, json.length(), "incorrect number of elements");
-    JSONObject taskAttempt = attempts.getJSONObject("taskAttempt");
-    JSONArray arr = new JSONArray();
-    arr.put(taskAttempt);
+    JSONArray arr = attempts.getJSONArray("taskAttempt");
     for (TaskAttempt att : task.getAttempts().values()) {
       TaskAttemptId id = att.getID();
       String attid = MRApps.toString(id);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to