【问题标题】:Jersey producing different output for JSON and XML from cglib beansJersey 从 cglib bean 为 JSON 和 XML 生成不同的输出
【发布时间】:2013-09-12 17:59:28
【问题描述】:

我想使用动态生成的 bean 作为 Jersey REST WS 的输出。我不知道在编译时会请求什么属性。我可以返回一个包含字段列表的 bean,但我想尝试返回一个具有动态创建属性的 bean,因为输出会更好一些。

我正在尝试使用 cglib 构建一个 bean 实例并将其返回到 Jersey 框架以编组为 JSON/XML。我遇到了下面的问题,如果有人可以提出建议,我将不胜感激。不知道能不能利用泛型的魔力或者创建自定义处理程序来解决。

使用的库:Tomcat 6.0.18、Java 1.6.0_17、Jersey v1.8、cglib v2.2

搜索WS

@Path("/search")
public class SearchWS
{
private static final Logger log = Logger.getLogger(SearchWS.class.getName());

@POST
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public GenericObject getXML(@Context final HttpServletRequest request, @FormParam("query") final String query)
        throws Exception
{
    log.debug("Entering");
    final IDAO dao = new DAOImpl();
    return dao.search(query).getResults().get(0);
}

}

GenericObject bean 类

@XmlRootElement(name = "object")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class GenericObject
{

}

DAO 根据查询创建键/值对映射并构建 GenericObject 子类实例

public GenericObject buildGenericBean(final Map<String, String> propertyValues) throws Exception
{
    log.debug("Entering");

    BeanGenerator bg = new BeanGenerator();
    bg.setSuperclass(GenericObject.class);

    bg.setNamingPolicy(new net.sf.cglib.core.NamingPolicy()
    {
        @Override
        public String getClassName(final String prefix, final String source, final Object key, final Predicate names)
        {
            return prefix + "Impl";
        }
    });

    Set<String> keys = propertyValues.keySet();
    for (String nextKey : keys)
    {
        bg.addProperty(nextKey, String.class);
    }
    GenericObject bean = (GenericObject) bg.create();

    for (String nextKey : keys)
    {
        setProperty(bean, nextKey, propertyValues.get(nextKey));
    }

    log.debug("Leaving");
    return bean;
}

当客户端请求 JSON 内容(“application/json”)时,它会根据作为表单参数提交的 SQL 查询产生一些不错的输出:

{
    "country": "DZ",
    "title": "foo",
    "theme": "foo",
    "subject": "foo",
    "owner_name": "foo",
    "creation_date": "16/05/2013 06:20:10 PM",
    "publication_needed": "1",
    "language_code": "en",
    "modify_date": "21/05/2013 05:08:15 PM",
    "classification": "0"
}

将请求的内容类型设置为 XML(“application/xml”)会导致以下错误。我曾希望泽西岛能确保输出是等价的,例如以文本内容作为属性值的属性命名的元素。不过,我不是 XML 编组方面的专家,所以可能会遗漏一些东西。如何在 XML 中获得等效的输出?

Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class xxx.model.GenericObjectImpl, and Java type class xxx.model.GenericObjectImpl, and MIME media type application/xml was not found

【问题讨论】:

    标签: xml json rest jersey cglib


    【解决方案1】:

    cglib 创建一个子类以创建代理。这意味着 Jersey 将收到 GenericObject 的子类,而不是直接实例。然而,注解XMLRootElement 没有声明为@Inherited,这样即使是GenericObject,这个代理子类也不会出现这个注解。

    由于 Jersey 在实际类型上没有找到这个注解,它告诉你它不知道如何处理它。不幸的是,这个问题不太容易用 cglib 解决。您可能想直接尝试其他检测库,例如 javassist 或 ASM。

    如果你想直接解决泽西岛的问题。但是,您可以创建自己的编组器来检查该类是否是 GenericObject 的子类,以便创建默认的 XML 输出。 (照顾泽西岛MessageBodyWriter 寻求帮助。)

    【讨论】:

      猜你喜欢
      • 2010-10-17
      • 2015-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-26
      • 2011-08-26
      • 2013-09-09
      相关资源
      最近更新 更多