2016-04-28 14 views
7

Ich habe Probleme in einem Jax-RS REST-Service beim Versuch, eine Entität mit Enumerationen über HTTP PUT zu aktualisieren.HTTP Put Enum mit JAX-RS REST-Service

Ich setze die Entity als JSON codiert, so dass die Enumerationen, die ich in diesem JSON verwende, als Strings geliefert werden.

ich folgende Fehler bekommen:

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) 

Feld Wert AGENT eine Aufzählung in der Entität Konto ist.

Ich bekomme nur diesen Fehler in Entities Entitäten, in anderen Fällen die HTTP PUT funktioniert gut.

Meine Vermutung ist, wie "AGENT" als Zeichenfolge in JSON geliefert wird, kann es nicht in einen Enum-Wert aufgelöst werden.

Gibt es eine einfache Problemumgehung, mit der ich gehen könnte?

Danke für Ihre Hilfe!

bearbeiten für etwas mehr Code:

Okay, die Enum wie folgt definiert ist:

@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 
} 

Der HTTP-PUT in REST-Dienst wie folgt aus:

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

mit Update- Funktion:

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

irgendwelche Vorschläge?

+0

Haben Sie die folgende Lösung versucht: http://stackoverflow.com/a/12292355/1346996? – aribeiro

+0

Danke für Ihren Vorschlag, ich habe das versucht, aber der Fehler bleibt gleich. – EsSuch

+1

Können Sie den eingehenden JSON und die Klasse, zu der sie deserialisiert werden soll, hinzufügen? – Ilya

Antwort

2

@XmlEnumValue Annotation deklariert, welcher String-Wert der Annotated Enum-Konstante zugeordnet wird. das heißt, wenn Sie schreiben, ist

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

dann CUSTOMER konstant lov.account.type.customer String abgebildet.

Also, wenn Sie möchten, dass CUSTOMER konstant CUSTOMER String abgebildet wird, dann müssen Sie

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

oder entfernen @XmlEnumValue Anmerkung dh

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


UPD Jetzt sehe ich, dass die Wurzel schreiben Das Problem ist die Vererbung. Wenn Sie versuchen, eine geerbte Klasse zu deserialisieren, verwendet EclipseLink standardmäßig das @ type-Feld, um zu bestimmen, welche Klasse für welche Eingabe instanziiert werden soll. Siehe this answer. Sie haben also verschiedene Möglichkeiten, abhängig von Ihren Umständen.

erster Weg (schmutzig genug)
Sie können versuchen, Ihren Supertyp mit @XmlDiscriminatorNode("fakeField") Es ist nur anwendbar, mit Anmerkungen versehen, wenn Sie ein Kind Klasse

Zweiten Weg
haben Wenn Sie genaue Beziehung zwischen AccountType Konstante und Unterklasse müssen Sie jede untergeordnete Klasse mit @XmlDiscriminatorValue Annotation annotieren.
Beispiel:

@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 { 

} 
+0

danke für den Rat, aber es funktioniert immer noch nicht. Irgendwelche anderen Vorschläge? – EsSuch

+0

Gleiche Ausnahme? – Ilya

+0

ja, 100% identisch. – EsSuch

1

Es ist nicht genau das gleiche Szenario, aber ich hatte ein ähnliches Problem in Jersey mit JSON und Aufzählungen.

Eine Sache, die ich in Ihrer Enumerationsdefinition sehen ist, dass Sie für die ENUM einen benutzerdefinierten Namen angeben

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

Aber es scheint, dass Sie AGENTEN in den JSON-Daten sind zu senden. Solltest du stattdessen 'lov.account.type.agent' senden?