HTTP使用JAX放置枚举

尝试通过HTTP PUT更新包含枚举的实体时,我在Jax-RS REST服务中遇到问题。

我将实体编码为JSON,因此我在此JSON中使用的枚举以字符串形式提供。

我收到以下错误:

Exception [EclipseLink-43] (Eclipse Persistence Services - 2.6.2.qualifier): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing class for indicator field value [AGENT] of type [class java.lang.String].
Descriptor: XMLDescriptor(de.org.app.business.account.Account --> [DatabaseTable(account)])
    at org.eclipse.persistence.exceptions.DescriptorException.missingClassForIndicatorFieldValue(DescriptorException.java:940)
    at org.eclipse.persistence.internal.oxm.QNameInheritancePolicy.classFromRow(QNameInheritancePolicy.java:278)
    at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.classFromRow(TreeObjectBuilder.java:182)
    at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.classFromRow(TreeObjectBuilder.java:1)
    at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.initializeRecord(UnmarshalRecordImpl.java:512)
    at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.startElement(UnmarshalRecordImpl.java:748)
    at org.eclipse.persistence.internal.oxm.record.json.JsonStructureReader.parseRoot(JsonStructureReader.java:187)
    at org.eclipse.persistence.internal.oxm.record.json.JsonStructureReader.parse(JsonStructureReader.java:140)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:978)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:425)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:375)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:708)
    at org.eclipse.persistence.internal.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:643)
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:339)
    at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.readFrom(MOXyJsonProvider.java:668)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:256)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:235)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
    at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:74)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
    at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:271)
    at org.glassfish.jersey.server.internal.inject.EntityParamValueFactoryProvider$EntityValueFactory.provide(EntityParamValueFactoryProvider.java:96)
    at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.provide(ParamValueFactoryWithSource.java:71)
    at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:94)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:127)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$VoidOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:143)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:471)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:425)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:383)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:336)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:223)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
    at java.lang.Thread.run(Thread.java:745)

字段值代理是实体帐户中的枚举。

我只在包含枚举的实体中出现此错误,而在其他情况下,HTTP PUT正常工作。

我的猜测是,由于“AGENT”以JSON字符串的形式提供,因此无法解析为枚举值。

有什么简单的解决方法,我可以去?

谢谢你的帮助!

编辑更多代码:

好的,枚举是这样定义的:

@XmlType(name = "type")
@XmlEnum
public enum AccountType implements TranslatableEnum {
    @XmlEnumValue(value = "lov.account.type.customer")
    CUSTOMER("lov.account.type.customer"),
    @XmlEnumValue(value = "lov.account.type.agent")
    AGENT("lov.account.type.agent")
    //just getter/setter things following
}

REST服务中的HTTP PUT如下所示:

@PUT
@Path(value = "{id}")
@Consumes(value = MediaType.APPLICATION_JSON)
public void edit(@PathParam(value = "id") final String id, final T entity) {
    getRepository().update(entity);
}

具有更新功能:

public T update(@Observes @Update T entity) {
    getEntityManager().merge(entity);
    return entity;
}

有什么建议么?


@XmlEnumValue注解声明哪个字符串值映射到注释的枚举常量。 即当你写作时

@XmlEnumValue(value = "lov.account.type.customer")
CUSTOMER("lov.account.type.customer")

那么CUSTOMER常量被映射到lov.account.type.customer字符串。

所以如果你想让CUSTOMER常量被映射到CUSTOMER字符串,那么你需要写

@XmlEnumValue(value = "CUSTOMER")
CUSTOMER("lov.account.type.customer")

或删除@XmlEnumValue注释即

@XmlEnum
public enum AccountType implements TranslatableEnum {
    CUSTOMER("lov.account.type.customer"),
    AGENT("lov.account.type.agent")
    //...
}


UPD现在我看到问题的根源是继承。 如果尝试反序列化继承的类EclipseLink,默认情况下使用@type字段来确定哪个类应该实例化哪个输入。 看到这个答案。 所以根据你的情况你有几种方法可以去。

第一种方式(够脏)
您可以尝试使用@XmlDiscriminatorNode("fakeField")注释您的超类型。仅当您有一个子类时才适用

第二种方式
如果你在AccountType常量和子类之间有确切的关系,你需要用@XmlDiscriminatorValue注解来注释每个子类。
例:

@XmlRootElement
public static class Parent {
    AccountType type;

    public AccountType getType() {
        return type;
    }

    public void setType(AccountType type) {
        this.type = type;
    }
}


@XmlDiscriminatorValue("AGENT")
public static class Agent extends Parent {

}

@XmlDiscriminatorValue("CUSTOMER")
public static class Customer extends Parent {

}

这不完全相同的情况,但我在泽西使用JSON和枚举类似的问题。

我在你的枚举定义中看到的一件事是你为枚举指定了一个自定义名称

AGENT("lov.account.type.agent")

但看起来你是在JSON数据中发送代理。 你不应该发送'lov.account.type.agent'吗?

链接地址: http://www.djcxy.com/p/33715.html

上一篇: HTTP Put Enum using JAX

下一篇: How to create emulator for ONEPLUS TWO?