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]