7

我们正在使用 IBM(s) 捆绑的 Apache Wink 为我们的应用程序提供 JAXRS 端点。我们正在编写 Websphere 8.5.5。由于我们符合 servlet 3.0,我们使用“程序化”方式配置 JaxRS 应用程序,这意味着 web.xml 中没有条目,我们依赖于类扫描来查找带注释的 jax rs 资源。一般来说,它工作正常。

   @ApplicationPath("/api/v1/") 
   public class MyApplication  extends Application{

此版本的 Websphere 与 Apache Wink 一起使用 Jackson 1.6.x 进行 JSON 反序列化,并且通常运行良好。我们希望更改对象映射器的一些默认值

所以我们定义了一个客户上下文解析器,只需要改变一些 se/deserialzation 属性。

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class CustomJackssonConverter implements ContextResolver<ObjectMapper> {

    final ObjectMapper defaultObjectMapper;

    public AibasJackssonConverter() {
        defaultObjectMapper = createDefaultMapper();
    }
   ...       
 mapper.getSerializationConfig().set(SerializationConfig.Feature.INDENT_OUTPUT, true);

在 JAX-RS 调用期间,我们可以看到容器注册了新的 Provider,没有错误

问题是,配置不是“遵循”的,从日志中我可以看到 Wink 引擎正在查找 WinkJacksonProvider,这反过来..返回一个遵循 Jackson(s) 默认值的 JacksonProvider?

有没有办法改变这个默认值?

我已尝试按照此处所示更改 Application 对象的实现,以便以编程方式配置提供程序,但它不起作用。

http://www.ibm.com/developerworks/java/library/wa-aj-jackson/index.html

任何提示或提示?

非常感谢

4

4 回答 4

3

我找到了使用 ContextResource 的工作解决方案。

您需要 Jackson JAX-RS 提供程序依赖项。Maven 示例:

<dependency>
  <groupId>com.fasterxml.jackson.jaxrs</groupId>
  <artifactId>jackson-jaxrs-json-provider</artifactId>
  <version>2.9.7</version>
</dependency>

接下来你可以实现 ContextResolver

@Provider
public class JacksonConfig implements ContextResolver<ObjectMapper> {

    private final ObjectMapper objectMapper;

    public JacksonConfig() {
        objectMapper = createObjectMapper();
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return objectMapper;
    }

    private ObjectMapper createObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        // some mapper configurations
        return mapper;
    }

}

最后,您必须在 Application 类中注册 JacksonJaxbJsonProvider 和 ContextResolver。

public class RestApplicationConfig extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new java.util.HashSet<>();
        resources.add(JacksonJaxbJsonProvider.class);
        resources.add(JacksonConfig.class);
        // Add other resources
        return resources;
    }
}
于 2018-11-02T11:36:32.967 回答
3

I solved this problem by just implementing a MessageBodyWriter class, like this:

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class DefaultMessageBodyWriter implements MessageBodyWriter<Object> {

    @Override
    public long getSize(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public void writeTo(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
        mapper.writeValue(entityStream, object);
    }
}

Every time a JSON serialization is requested, this class comes into action and finally its writeTo method is invoked.

Here SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS is turned off, as requested by WebSphere.

于 2015-12-18T19:08:00.413 回答
0

我使用的是自由配置文件服务器 20.0.0.0 和 eclipselink 2.7.6。默认情况下,JAXRS 使用来自 eclipselink 的 MoxyJsonProvider,它会抛出“检测到循环”错误。我想用我的 ObjectMapper 或 Jackson Json 提供程序覆盖默认的 JAXB Moxy 提供程序。

public Set<Class<?>> getClasses()不工作。我必须创建另一个类文件来创建public class JaxbJsonProvider extends JacksonJaxbJsonProvider它并将其注释为@Provider。这个解决方案对我有用。

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;

@Provider
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class JaxbJsonProvider extends JacksonJaxbJsonProvider {

}

另一个文件是

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Provider
public class JacksonObjectMapperProvider implements ContextResolver<ObjectMapper> {

    final ObjectMapper defaultObjectMapper;

    public JacksonObjectMapperProvider() {
        defaultObjectMapper = createDefaultMapper();
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return defaultObjectMapper;
    }

    public static ObjectMapper createDefaultMapper() {

        log.info(String.format("Registering ObjectMapper modules"));


        ObjectMapper mapper = new ObjectMapper();

        mapper.disable(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapper.configure(MapperFeature.USE_GETTERS_AS_SETTERS, true);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        return mapper;
    }

}

重新启动您的自由配置文件服务器,REST API 将正常工作。请注意,@Slf4j 仅用于记录语句,映射器配置选项是您可以跳过的。Liberty 建议使用mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);. 所有其他都根据您的项目设置。

于 2020-02-20T11:51:28.387 回答
-1

我在 WAS v8.0.0.x 中使用 MOXy 而不是 Jackson。

为了覆盖杰克逊,我实现了我的应用程序类:

@Named
@ApplicationScoped
@ApplicationPath("/resources/")
public class WinkApplication extends Application implements Serializable {

private static final long serialVersionUID = 1L;

@Override
public Set<Class<?>> getClasses() {
    Set<Class<?>> classes = new HashSet<Class<?>>();
    classes.add(WinkResource.class);
    classes.add(WinkMOXyJsonProvider.class);
    classes.add(WinkResponseException.class);
    classes.add(WinkResponseExceptionMapper.class);
    return classes;
}
}

但是,我注意到 WAS 似乎忽略了以下注释:

@ApplicationPath("/resources/")

所以,我求助于使用 web.xml:

<!-- Wink Servlet -->
<servlet>
    <description>JAX-RS Tools Generated - Do not modify</description>
    <servlet-name>JAX-RS Servlet</servlet-name>
    <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.company.team.project.webservices.config.WinkApplication</param-value>
    </init-param>
    <!-- <init-param>
        <param-name>propertiesLocation</param-name>
        <param-value>/WEB-INF/my-wink-properties.properties</param-value>
    </init-param> -->
    <load-on-startup>1</load-on-startup>
    <enabled>true</enabled>
    <async-supported>false</async-supported>
</servlet>

<!-- Wink Servlet Mapping -->
<servlet-mapping>
    <servlet-name>JAX-RS Servlet</servlet-name>
    <url-pattern>/resources/*</url-pattern>
</servlet-mapping>

关键是,由于 WAS 或 Wink 在使用 ApplicationPath 注释时似乎忽略了 Application 实现,因此 Wink 加载了默认的 Application 类,该类默认使用 Jackson。

是的,我已经阅读了文档,甚至在线观看了 IBM 视频,其中提到 @ApplicationPath 允许您避免 XML 配置,但是这个问题似乎是一个错误。

更新:

另一种方法可能是 David Blevins 在另一篇 SO 帖子中提到的。

查看使用 JAX-RS 部分

于 2015-03-20T08:49:51.257 回答