我有一个使用Java,MOXy和Jersey的服务器应用程序。将单个对象编组到JSON非常有效,当我的函数返回带有一些对象的列表(List<Entity>
)时,编组也很有效。
但是现在我添加了一个名为Response的类,它包含一些有关函数调用的附加信息,以及一个通用列表,如上所示。如果我为我拥有的每个实体创建一个特殊的Response类,编组就可以了,但它并不是很优雅。所以我将Response类修改为通用(Response<T>
包含List<T>
)。
但现在编组停止工作了。我在stackoverflow上尝试了一些解决方案,但没有一个工作。所以,请帮帮我!谢谢!
更新:添加最少的工作样本以指出我的问题
的build.gradle
apply plugin: 'java'
apply plugin: 'war'
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
def jerseyVersion = '2.4.1'
compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet', version: jerseyVersion
compile group: 'org.glassfish.jersey.media', name: 'jersey-media-moxy', version: jerseyVersion
}
Server.java
package org.minimal.demo.server;
import org.glassfish.jersey.server.ResourceConfig;
import javax.ws.rs.ApplicationPath;
@ApplicationPath("api")
public class Server extends ResourceConfig {
public Server() {
packages("org.minimal.demo.server.api");
register(JsonMoxyConfigurationContextResolver.class);
}
}
JsonMoxyConfigurationContextResolver.java
package org.minimal.demo.server;
import org.glassfish.jersey.moxy.json.MoxyJsonConfig;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import java.util.HashMap;
import java.util.Map;
@Provider
public class JsonMoxyConfigurationContextResolver implements ContextResolver<MoxyJsonConfig> {
private final MoxyJsonConfig config;
public JsonMoxyConfigurationContextResolver() {
config = new MoxyJsonConfig()
.setIncludeRoot(false)
.setValueWrapper("$")
.setFormattedOutput(true)
.setNamespaceSeparator(':');
}
@Override
public MoxyJsonConfig getContext(Class<?> type) {
return config;
}
}
SomeEntity.java
package org.minimal.demo.server.entity;
public class SomeEntity {
public int value;
public SomeEntity() {
}
public SomeEntity(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
GenericResponse.java
package org.minimal.demo.server.response;
import java.util.ArrayList;
import java.util.List;
public class GenericResponse<T> {
public List<T> items = new ArrayList<T>();
public String msg;
public GenericResponse() {
}
public GenericResponse(String msg) {
this.msg = msg;
}
public void addItem(T item) {
items.add(item);
}
public List<T> getItems() {
return items;
}
public String getMsg() {
return msg;
}
}
SomeApi.java
package org.minimal.demo.server.api;
import org.minimal.demo.server.entity.SomeEntity;
import org.minimal.demo.server.response.GenericResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.List;
@Path("/something")
public class SomeApi {
@GET
@Path("/a")
public String simpleString() {
return "SomeApi.simpleString";
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/b")
public SomeEntity getSomeEntity() {
return new SomeEntity(42);
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/c")
public List<SomeEntity> getSomeEntityList() {
List<SomeEntity> ret = new ArrayList<SomeEntity>();
ret.add(new SomeEntity(42));
ret.add(new SomeEntity(1337));
return ret;
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/d")
public GenericResponse<SomeEntity> getGenericResponse() {
GenericResponse<SomeEntity> ret = new GenericResponse<SomeEntity>("SomeApi.getGenericResponse");
ret.addItem(new SomeEntity(42));
ret.addItem(new SomeEntity(1337));
ret.addItem(new SomeEntity(23));
return ret;
}
}
当我构建战争并将其部署在Tomcat中时,几乎所有内容都可以正常运行。开口
http://localhost:8080/genresp-1.0/api/something/a
http://localhost:8080/genresp-1.0/api/something/b
http://localhost:8080/genresp-1.0/api/something/c
在浏览器中,显示预期结果。但是当我浏览
时http://localhost:8080/genresp-1.0/api/something/d
抛出以下异常:
Dez 12, 2013 9:21:46 PM org.glassfish.jersey.server.ServerRuntime$Responder mapException
WARNING: WebApplicationException cause:
javax.xml.bind.MarshalException
- with linked exception:
[Exception [EclipseLink-25003] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred marshalling the object
Internal Exception: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class org.minimal.demo.server.response.GenericResponse was not found in the project. For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.]
at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:403)
at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.java:808)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:243)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:230)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:149)
at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:103)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:149)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:88)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:149)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1139)
at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:557)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:381)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:371)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:262)
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:318)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:983)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:361)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Caused by: Exception [EclipseLink-25003] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred marshalling the object
Internal Exception: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class org.minimal.demo.server.response.GenericResponse was not found in the project. For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
at org.eclipse.persistence.exceptions.XMLMarshalException.marshalException(XMLMarshalException.java:97)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:911)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:848)
at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:401)
... 41 more
Caused by: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class org.minimal.demo.server.response.GenericResponse was not found in the project. For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
at org.eclipse.persistence.exceptions.XMLMarshalException.descriptorNotFoundInProject(XMLMarshalException.java:139)
at org.eclipse.persistence.internal.oxm.Context$ContextState.getSession(Context.java:143)
at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:787)
at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:1)
at org.eclipse.persistence.internal.oxm.Context.getSession(Context.java:451)
at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:356)
at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:1)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:1119)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:869)
... 43 more