J'utilise Jersey 2.3
Ma classe de point de terminaison WS:
@Path("/employees")
public class EmployeeWSEndpoint {
@Context
Request request;
@GET
@Path("/allEmployees")
@Produces(MediaType.APPLICATION_JSON)
public List<Employee> getAllEmployees() {
System.out.println("In EmployeeWSEndpoint.getAllEmployees()");
EmployeeService employeeService = new EmployeeServiceImpl();
return employeeService.getAllEmployees();
}
@GET
@Path("/allDept")
@Produces(MediaType.APPLICATION_JSON)
public List<String> getAllDept() {
System.out.println("In EmployeeWSEndpoint.getAllDept()");
List<String> deptNames = new ArrayList<>();
deptNames.add("CoE");
deptNames.add("iLabs");
return deptNames;
}
@GET
@Path("/allDeptPOJO")
@Produces(MediaType.APPLICATION_JSON)
public TempPOJO getAllDeptPOJO() {
System.out.println("In EmployeeWSEndpoint.getAllDeptPOJO");
TempPOJO tempPOJO = new TempPOJO();
return tempPOJO;
}
}
POJO employé:
public class Employee {
private int id;
private String firstName;
private String middleName;
private String lastName;
private Date dob;
private int deptId;
public Employee() {
}
public Employee(String firstName, String middleName, String lastName,
Date dob, int deptId) {
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.dob = dob;
this.deptId = deptId;
}
public Employee(int id, String firstName, String middleName,
String lastName, Date dob, int deptId) {
this.id = id;
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.dob = dob;
this.deptId = deptId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public int getDeptId() {
return deptId;
}
public void setDeptId(int deptId) {
this.deptId = deptId;
}
@Override
public String toString() {
return firstName + " " + middleName + " " + " " + lastName;
}
}
Un POJO temporaire:
public class TempPOJO {
private List<String> deptNames;
public List<String> getDeptNames() {
deptNames = new ArrayList<>();
deptNames.add("CoE");
deptNames.add("iLabs");
return deptNames;
}
public void setDeptNames(List<String> deptNames) {
this.deptNames = deptNames;
}
}
Lister le ou les résultats pour différentes méthodes:
tous les employés
[{"deptId":1,"dob":"1978-06-19","firstName":"Garfield","id":0,"lastName":"Arbuckle","middleName":"John"},{"deptId":1,"dob":"1946-07-07","firstName":"John","id":0,"lastName":"Rambo","middleName":"R"}]
/allDept
In EmployeeWSEndpoint.getAllDept()
Oct 01, 2013 3:31:08 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 Java.lang.String 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:562)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.Java:357)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.Java:347)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.Java:258)
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:235)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.Java:983)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.Java:359)
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:171)
at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:99)
at org.Apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.Java:947)
at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:408)
at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:1009)
at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:589)
at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:310)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at Java.lang.Thread.run(Unknown Source)
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 Java.lang.String 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 Java.lang.String 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:568)
at org.Eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.Java:1096)
at org.Eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.Java:869)
... 43 more
/allDeptPOJO
{"deptNames":["CoE","iLabs"]}
J'ai quelques requêtes :
Note : Je veux la réponse en JSON dans la plupart des cas.
Modification du fichier web.xml pour utiliser Jackson:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://Java.Sun.com/xml/ns/javaee"
xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee http://Java.Sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Jersey</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.ws.jaxrs.jersey</param-value>
</init-param>
<init-param>
<param-name>jersey.config.disableMoxyJson.server</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.ws.jaxrs.jersey;org.codehaus.jackson.jaxrs</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
J'ai eu l'exception suivante:
In EmployeeWSEndpoint.getAllDept()
Nov 07, 2013 10:04:12 AM org.Apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Jersey REST Service] in context with path [/Jersey] threw exception [org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class Java.util.ArrayList, genericType=Java.util.List<Java.lang.String>.] with root cause
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class Java.util.ArrayList, genericType=Java.util.List<Java.lang.String>.
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.Java:227)
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:562)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.Java:357)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.Java:347)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.Java:258)
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:235)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.Java:983)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.Java:359)
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:304)
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:224)
at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:169)
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:100)
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:405)
at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:964)
at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:515)
at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:302)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at Java.lang.Thread.run(Unknown Source)
Jackson est la meilleure solution pour moi pour le moment.
Pour utiliser Jackson en tant que fournisseur JSON, vous devez ajouter le module jersey-media-json-jackson
à votre fichier pom.xml
:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.7</version>
</dependency>
Remarque: La fonction de découverte automatique ne fonctionne pas.
final Client client = ClientBuilder.newBuilder()
.register(JacksonFeature.class)
.build();
final Application application = new ResourceConfig()
.packages("my.rest.package")
.register(JacksonFeature.class);
Consultez également l'exemple officiel Jersey json-jackson .
Je ne sais pas pourquoi jersey startet a adopté MOXy comme fournisseur JSON par défaut, mais c'est évidemment une mauvaise idée.
Les problèmes que vous (et moi-même - ainsi que d’autres) rencontrons sont le résultat de MOXy beeing incapable de mapper des collections de types Java simples (comme String) - c’est ridicule à mon humble avis. Les autres fournisseurs (comme jackson ) n'ont pas ce problème, donc le changement aidera certainement.
Voici ce que j'ai fait:
Indiquez à Jersey not d'utiliser MOXy. Ajoutez ceci à votre web.xml:
<init-param>
<param-name>jersey.config.disableMoxyJson.server</param-name>
<param-value>true</param-value>
</init-param>
Ajoutez Jackson à votre pom. Quelque chose comme ça va faire:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.12</version>
</dependency>
Dites à Jersey de scanner les paquets de Jackson Jackson Il trouvera (et utilisera) les fournisseurs JSON fournis par Jackson:
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.example.your.package;org.codehaus.jackson.jaxrs</param-value>
</init-param>
Remarque: Je suis le EclipseLink JAXB (MOXy) lead et membre du JAXB (JSR-222) expert groupe.
L'exception que vous frappez est due à un bogue dans MOXyJsonProvider
de MOXy. MOXyJsonProvider
est une implémentation des interfaces JAX-RS MessageBodyReader
/MessageBodyWriter
. J'ai changé la méthode isWriteable
pour renvoyer false pour List<String>
pour renvoyer false afin qu'un autre fournisseur puisse la gérer.
J'ai également ouvert la demande d'amélioration suivante pour que cette prise en charge soit ajoutée à MOXy:
Vous pouvez utiliser RestEasy comme implémentation JAX-RS
GlassFish4 utilise Jersey/MOXy comme implémentation de JAX-RS. Ils ont des problèmes de mappage des collections de types Java simples (comme String) vers JSON - https://bugs.Eclipse.org/bugs/show_bug .cgi? id = 417723
WildFly et JBoss utilisent RestEasy/Jackson comme implémentation de JAX-RS et la cartographie ne pose aucun problème.
Vous pouvez utiliser RestEasy au lieu de Jersey dans n’importe quel serveur d’applications Java, par exemple. WildFly (JBoss), GlassFish ou Tomcat,
remplacez simplement:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
avec:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-servlet-initializer</artifactId>
<version>3.0.7.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.7.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.0.7.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.0.7.Final</version>
<scope>compile</scope>
</dependency>
Cela fonctionne pour moi.
Meilleures salutations de Lublin en Pologne :)
J'ai eu le même problème en renvoyant un objet List<String>
. Je l'ai enveloppé dans une classe RestStringList
et cela fonctionne. Si nous en avons plus à faire, je pourrais passer à Jackson.
import Java.io.Serializable;
import Java.util.ArrayList;
import Java.util.List;
public class RestStringList implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> stringList = null;
public RestStringList() {
this.stringList = new ArrayList<String>();
}
public void setStringList(List<String> stringList) {
this.stringList = new ArrayList<String>(stringList);
}
public List<String> getStringList() {
return stringList;
}
public String toString() {
return "{ strings=" + stringList + " }";
}
}