使用 Java EE 7 / Glassfish 4.1 编组/解组 JSON 导致空对象
Marshaling / Demarshaling JSON with Java EE 7 / Glassfish 4.1 results in null object
我从 Java EE 6 升级到 Java EE 7,我的一些 REST 服务停止工作。缩小范围,似乎这种变化似乎是在 Java EE 7 中 Jersey 从 Jackson 切换到 MOXy 时发生的。
我的服务是这样的:
@Stateless
@Path("access")
public class AccessFacadeREST extends AbstractFacade<Access> {
@PersistenceContext(unitName = "AccessServerPU")
private EntityManager em;
public AccessFacadeREST() {
super(Access.class);
}
@POST
@Consumes({"application/xml", "application/json"})
@Produces({"application/xml", "application/json"})
public ObjectResponse create(@Context HttpServletRequest requestContext,
@Context SecurityContext context,
ObjectRequest<Access> req) {
req.setHostname(requestContext.getRemoteAddr());
return AccessValidation.create(em, req);
}
}
此处 req
为空,因此在使用 JSON 呈现时生成 NullPointerException
。当显示为 XML 时,它工作正常。 ObjectRequest
是一个通用的 class 我用它来为几种不同类型的请求包装带有身份验证内容标准的请求。
我测试了与 return 一个充满垃圾数据的 ObjectRequest<Access>
实例类似的 @GET
服务。它在使用 XML 时再次运行良好,但是当我尝试 return JSON 时 returns null
(无一例外)。
我发现 Java EE7 REST server no longer returning List as JSON 对理解潜在问题很有用,但我不知道如何让它在我的情况下起作用。我的 ApplicationConfig
class 看起来像:
@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
@Override
public Set<Object> getSingletons() {
Set<Object> set = new HashSet<>();
log.info("Enabling custom Jackson JSON provider");
set.add(new JacksonJsonProvider());
return set;
}
@Override
public Map<String, Object> getProperties() {
Map<String, Object> map = new HashMap<>();
log.info("Disabling MOXy JSON provider");
map.put("jersey.config.disableMoxyJson.server", true);
return map;
}
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
addRestResourceClasses(resources);
return resources;
}
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(AccessFacadeREST.class);
}
}
我想我需要配置 ApplicationConfig class 才能使用 Jackson,但我不知道如何概括我找到的解决方案来涵盖我的情况。所以,真的有两个问题:
- 我是否正确地将潜在问题描述为某种 MOXy 缺陷?
- 我如何使用 MOXy 或 Jackson 解决此问题(我没有偏好,只要它有效)?
设置:
- Netbeans 8.0.2
- 玻璃鱼 4.1
- JDK 8 / JRE 8U25(64 位)
编辑 以回应以下问题...
项目 pom.xml
具有以下条目:
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.4</version>
</dependency>
您应该可以通过禁用 MOXy(在 getClasses()
中注册下面的 class)并摆脱您的 set.add(new JacksonJsonProvider());
单例来解决这个问题。我将它用于我所有的 GF4 项目以强制 Jersey 使用 Jackson。
/**
* Feature to disable Moxy and Enable Jackson processing
*/
private static class Jackson2Feature implements Feature {
@Override
public boolean configure(FeatureContext context) {
final String disableMoxy = PropertiesHelper.getPropertyNameForRuntime(
CommonProperties.MOXY_JSON_FEATURE_DISABLE,
context.getConfiguration().getRuntimeType());
context.property(disableMoxy, true);
// add the default Jackson exception mappers and allow jaxb annotations
context.register(JsonParseExceptionMapper.class);
context.register(JacksonJaxbJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class);
return true;
}
}
我从 Java EE 6 升级到 Java EE 7,我的一些 REST 服务停止工作。缩小范围,似乎这种变化似乎是在 Java EE 7 中 Jersey 从 Jackson 切换到 MOXy 时发生的。
我的服务是这样的:
@Stateless
@Path("access")
public class AccessFacadeREST extends AbstractFacade<Access> {
@PersistenceContext(unitName = "AccessServerPU")
private EntityManager em;
public AccessFacadeREST() {
super(Access.class);
}
@POST
@Consumes({"application/xml", "application/json"})
@Produces({"application/xml", "application/json"})
public ObjectResponse create(@Context HttpServletRequest requestContext,
@Context SecurityContext context,
ObjectRequest<Access> req) {
req.setHostname(requestContext.getRemoteAddr());
return AccessValidation.create(em, req);
}
}
此处 req
为空,因此在使用 JSON 呈现时生成 NullPointerException
。当显示为 XML 时,它工作正常。 ObjectRequest
是一个通用的 class 我用它来为几种不同类型的请求包装带有身份验证内容标准的请求。
我测试了与 return 一个充满垃圾数据的 ObjectRequest<Access>
实例类似的 @GET
服务。它在使用 XML 时再次运行良好,但是当我尝试 return JSON 时 returns null
(无一例外)。
我发现 Java EE7 REST server no longer returning List as JSON 对理解潜在问题很有用,但我不知道如何让它在我的情况下起作用。我的 ApplicationConfig
class 看起来像:
@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
@Override
public Set<Object> getSingletons() {
Set<Object> set = new HashSet<>();
log.info("Enabling custom Jackson JSON provider");
set.add(new JacksonJsonProvider());
return set;
}
@Override
public Map<String, Object> getProperties() {
Map<String, Object> map = new HashMap<>();
log.info("Disabling MOXy JSON provider");
map.put("jersey.config.disableMoxyJson.server", true);
return map;
}
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
addRestResourceClasses(resources);
return resources;
}
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(AccessFacadeREST.class);
}
}
我想我需要配置 ApplicationConfig class 才能使用 Jackson,但我不知道如何概括我找到的解决方案来涵盖我的情况。所以,真的有两个问题:
- 我是否正确地将潜在问题描述为某种 MOXy 缺陷?
- 我如何使用 MOXy 或 Jackson 解决此问题(我没有偏好,只要它有效)?
设置:
- Netbeans 8.0.2
- 玻璃鱼 4.1
- JDK 8 / JRE 8U25(64 位)
编辑 以回应以下问题...
项目 pom.xml
具有以下条目:
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.4</version>
</dependency>
您应该可以通过禁用 MOXy(在 getClasses()
中注册下面的 class)并摆脱您的 set.add(new JacksonJsonProvider());
单例来解决这个问题。我将它用于我所有的 GF4 项目以强制 Jersey 使用 Jackson。
/**
* Feature to disable Moxy and Enable Jackson processing
*/
private static class Jackson2Feature implements Feature {
@Override
public boolean configure(FeatureContext context) {
final String disableMoxy = PropertiesHelper.getPropertyNameForRuntime(
CommonProperties.MOXY_JSON_FEATURE_DISABLE,
context.getConfiguration().getRuntimeType());
context.property(disableMoxy, true);
// add the default Jackson exception mappers and allow jaxb annotations
context.register(JsonParseExceptionMapper.class);
context.register(JacksonJaxbJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class);
return true;
}
}