I'm working with Jersey (jaxrs-ri-2.7), Tomcat 7.0.47 and Java 1.7.0_51. Due to firewalls, I can't use Maven. My goal is to do a JSON RESTful web service. I cannot get MOXy to work though I'm told it's included with the version of Jersey. At one point, I could get Jersey to return XML. When I invoke my web service via a browser, this is what I get:
我正在使用Jersey (jaxrs-ri-2.7)、Tomcat 7.0.47和Java 1.7.0_51。由于防火墙的原因,我不能使用Maven。我的目标是做一个JSON RESTful web服务。我不能让MOXy去工作,尽管我被告知它包含了泽西岛的版本。在某种程度上,我可以让Jersey返回XML。当我通过浏览器调用我的web服务时,我得到的是:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException:
MessageBodyWriter not found for media type=application/json, type=class com.pracht.test.Calculation, genericType=class com.pracht.test.Calculation.
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:247)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:103)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:88)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1154)
at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:571)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:378)
...
This is my provider class:
这是我的提供者类:
package com.pracht.test;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import com.owlike.genson.Genson;
import com.owlike.genson.TransformationException;
@Provider
@Produces("application/json")
public class JsonProvider implements MessageBodyWriter<Calculation> {
public JsonProvider() throws IOException{
try {
PrintWriter pw=new PrintWriter(
new BufferedOutputStream(new FileOutputStream("c:\\test.txt")));
pw.println("Reached JsonProvider()");
pw.close();
} catch(IOException e){
e.printStackTrace();
}
}
@Override
public long getSize(Calculation arg0, Class<?> arg1, Type arg2,
Annotation[] arg3, MediaType arg4) {
return 0;
}
@Override
public void writeTo(Calculation calculation,
Class<?> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream)
throws IOException, WebApplicationException {
Genson genson = new Genson();
try {
String json=genson.serialize(calculation);
entityStream.write(json.getBytes());
} catch (TransformationException e) {
e.printStackTrace();
throw new WebApplicationException("Serialization error",e);
}
}
@Override
public boolean isWriteable(Class<?> classType, Type arg1, Annotation[] arg2,
MediaType arg3) {
return classType == Calculation.class;
}
}
I added the PrintWriter in the constructor to hopefully tell me that least an object got constructed and to put the results where I can see it. I just wanted something quick and didn't want to figure out whatever logging API happens to be in use.
我在构造函数中添加了PrintWriter,希望告诉我至少一个对象被构造了,并将结果放到我可以看到的地方。我只是想要一些快速的东西,不想弄清楚任何正在使用的日志API。
This is my web resource:
这是我的网络资源:
package com.pracht.test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/calc")
public class CalcRest {
public CalcRest(){
System.out.println("Reached CalcRest()");
}
@GET
@Path("/add/{a}/{b}")
@Produces("application/json")
public Calculation addPlainText(@PathParam("a") double a,
@PathParam("b") double b) {
System.out.println("Reached addPlainText()");
return new Calculation().withProblem(a+"+"+b).withAnswer(a+b);
}
}
This is the call I make using Firefox:
这是我用火狐打的电话:
http://localhost:8080/Contacts/rest/calc/add/1/2
As a side note, would Java developers like it if there were just one library which actually handled JSON web services using annotations, out of the box. One that just worked?
顺便提一下,如果只有一个库可以直接使用注释处理JSON web服务,Java开发人员会喜欢它吗?一个工作?
1 个解决方案
#1
1
Why did you write a MessageBodyWriter for Genson? Genson has its own that should be picked automatically when you have Genson in your classpath.
你为什么要为Genson写一篇消息体的文章?Genson有它自己的,当您在类路径中有Genson时,应该自动选择。
If it is not the case I guess that Jersey finds another provider for JSON (moxy perhaps) and thus doesn't pick Genson. If this is the case you can try to create a folder META-INF/services in your classpath and define there Genson as your provider (this should override the other providers). You can have a look at how it is done in Genson here.
如果不是这种情况,我猜想Jersey会找到另一个JSON提供者(可能是moxy),因此不会选择Genson。如果是这样,您可以尝试在类路径中创建一个文件夹META-INF/services,并在其中定义Genson作为您的提供者(这应该覆盖其他提供者)。你可以看看在Genson是怎么做的。
Also you should take latest version of Genson, 0.99, it has a couple of improvments such as the implementation of JSR 353 that tries to provide a "standard" for JSON Parsing (not databinding) in Java.
您还应该使用Genson的最新版本0.99,它有一些改进,比如JSR 353的实现,它试图为Java中解析JSON(而不是数据库)提供“标准”。
#1
1
Why did you write a MessageBodyWriter for Genson? Genson has its own that should be picked automatically when you have Genson in your classpath.
你为什么要为Genson写一篇消息体的文章?Genson有它自己的,当您在类路径中有Genson时,应该自动选择。
If it is not the case I guess that Jersey finds another provider for JSON (moxy perhaps) and thus doesn't pick Genson. If this is the case you can try to create a folder META-INF/services in your classpath and define there Genson as your provider (this should override the other providers). You can have a look at how it is done in Genson here.
如果不是这种情况,我猜想Jersey会找到另一个JSON提供者(可能是moxy),因此不会选择Genson。如果是这样,您可以尝试在类路径中创建一个文件夹META-INF/services,并在其中定义Genson作为您的提供者(这应该覆盖其他提供者)。你可以看看在Genson是怎么做的。
Also you should take latest version of Genson, 0.99, it has a couple of improvments such as the implementation of JSR 353 that tries to provide a "standard" for JSON Parsing (not databinding) in Java.
您还应该使用Genson的最新版本0.99,它有一些改进,比如JSR 353的实现,它试图为Java中解析JSON(而不是数据库)提供“标准”。