Java jax-rs Jersey @Post 响应实体为空
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19534564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jax-rs Jersey @Post Response entity is empty
提问by HankCa
I'm trying to @POST a user-created object and get a Response with a different user-created payload as the entity. Although the object returned exists and is populated, on the client end it is empty.
我正在尝试 @POST 用户创建的对象,并使用不同的用户创建的有效负载作为实体获取响应。虽然返回的对象存在并被填充,但在客户端它是空的。
Client sent / server received object:
客户端发送/服务器接收对象:
@XmlRootElement
public class TweetQuery {
String query;
List<TweetQueryTweet> tweets = new ArrayList<>();
// setters and getters
}
public class TweetQueryTweet {
private String id;
private String text;
// setters and getters
}
Server received / client sent object:
服务器接收/客户端发送对象:
@XmlRootElement
public class TweetClusters {
List<TweetCluster> tweetClusters = new ArrayList<>();
// setters and getters
}
public class TweetCluster {
List<String> labels = new ArrayList<>();
List<String> docs = new ArrayList<>();
// setters and getters
}
Client (Arquillian) Test:
客户端(Arquillian)测试:
@Test
@RunAsClient
public void test01SeeSomething(@ArquillianResource URL deploymentUrl) throws ... {
final URI targetURI = ...;
System.out.println(" test target:" + targetURI.toASCIIString());
Entity<TweetQuery> tweetQuery = Entity.entity(getTestTweetQuery(), MediaType.APPLICATION_JSON);
Client client = ClientBuilder.newBuilder().build();
WebTarget target = client.target(targetURI.toASCIIString());
Response response = target.request(MediaType.APPLICATION_JSON).post(tweetQuery);
TweetClusters x = response.readEntity(TweetClusters.class);
System.out.println("Entity:" + x);
System.out.println("Response: " + response.getStatus());
assertEquals(Status.OK.getStatusCode(), response.getStatus());
assertNotNull(x);
assertThat(x.getTweetClusters().size()).isGreaterThan(0);
}
Jersey Post method:
泽西邮政方式:
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response clusterPost(TweetQuery tweetQuery) {
TweetClusters tweetClusters = clusterService.getTweetClusters(tweetQuery);
System.out.println("clusterPost - in - tweetQuery: " + tweetQuery);
System.out.println(" - out tweetClusters: " + tweetClusters);
return Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(tweetClusters).build();
}
Debug:
调试:
test target:http://localhost:18080/test//cluster
clusterPost - in - tweetQuery: [TweetQuery - query:TweetQuery query, tweets:[[TweetQueryTweet - id:1, text:text 1], [TweetQueryTweet - id:2, text:text 2], [TweetQueryTweet - id:3, text:text 3]]]
- out tweetClusters: [TweetClusters:[[TweetCluster - labels: [Other Topics], docs:[3, 2, 1]]]]
Entity:[TweetClusters:[]]
Response: 200
Line 2 - clusterPost - in -- shows TweetQuery is being marshalled properly. Line 3 - clusterPost - out -- shows the tweetClusters to be sent as the Response entity exists Line 4 - tweetClusters is not coming out of the request
第 2 行 - clusterPost - in - 显示 TweetQuery 正在正确编组。第 3 行 - clusterPost - out -- 显示当响应实体存在时要发送的 tweetClusters 第 4 行 - tweetClusters 未从请求中发出
Edit
编辑
I changed the REST method to return the tweetQuery that it receives as input and it is returned correctly. So its something about TweetClusters. Maybe I need a MessageBodyReader & Writer. Or a Moxy @XmlJavaTypeAdapter. But for what as Lists obviously work out of the box as TweetQuery works.
我更改了 REST 方法以返回它作为输入接收的 tweetQuery 并正确返回。所以它是关于 TweetClusters 的。也许我需要一个 MessageBodyReader 和 Writer。或者一个 Moxy @XmlJavaTypeAdapter。但是对于列表显然是开箱即用的,就像 TweetQuery 一样。
https://stackoverflow.com/users/383861/blaise-doughanare you out there? :)
https://stackoverflow.com/users/383861/blaise-doughan你在吗?:)
Am I missing something simple?
我错过了一些简单的东西吗?
采纳答案by HankCa
oK I worked it out. I unintentionally told a porkie-pie. When I said I had setters and getters I was mising the setter for TweetClusters. Then once fixed i had a constructor with an argument but no no-arg constructor. Once the no-arg constructor added it was all good.
好的,我解决了。我无意中告诉了一个猪肉馅饼。当我说我有 setter 和 getter 时,我想念 TweetClusters 的 setter。然后一旦修复,我有一个带参数的构造函数,但没有无参数的构造函数。添加无参数构造函数后,一切都很好。
In summary you need to have in objects to be (un)marshalled:
总之,您需要在对象中进行(未)编组:
- A no-arg constructor if you have an arg constructor
- Setters and getters for all the elements
- 如果您有 arg 构造函数,则为无参数构造函数
- 所有元素的 setter 和 getter
And if you have more complex types including Date and Calendar you need to have a Adapter @XmlJavaTypeAdapter
(Moxy) or @JsonSerialize.using
in Hymanson (or ??? in RESTeasy ...).
如果你有更复杂的类型,包括日期和日历,你需要有一个适配器@XmlJavaTypeAdapter
(Moxy) 或@JsonSerialize.using
在 Hymanson (或 ??? 在 RESTeasy ...)。
Interestingly I didn't need to have @XmlRootElement
(Moxy) though kept it there for good measure.
有趣的是,我不需要@XmlRootElement
(Moxy),尽管将它放在那里很好地衡量。
The complete answer is:
完整的答案是:
- The Client (Arquillian) Testis same as above
- The Jersey Post methodis same as above
The object classes that (un)marshall are:
@XmlRootElement public class TweetClusters { List tweetClusters = new ArrayList<>();
public void addCluster(Cluster c) { TweetCluster tweetCluster = new TweetCluster(c); tweetClusters.add(tweetCluster); } public List<TweetCluster> getTweetClusters() { return tweetClusters; } public void setTweetClusters(List<TweetCluster> tweetClusters) { this.tweetClusters = tweetClusters; } @Override public String toString() { return String.format("[TweetClusters:%s]", tweetClusters); }
}
public class TweetCluster { List labels = new ArrayList<>(); List docs = new ArrayList<>();
public TweetCluster() { } public TweetCluster(Cluster c) { labels.add(c.getLabel()); for (Document doc : c.getDocuments()) { docs.add(doc.getTitle()); } } public List<String> getLabels() { return labels; } public void setLabels(List<String> labels) { this.labels = labels; } public List<String> getDocs() { return docs; } public void setDocs(List<String> docs) { this.docs = docs; } @Override public String toString() { return String.format("[TweetCluster - labels: %s, docs:%s]", labels, docs); }
}
public class TweetQuery { String query;
List<TweetQueryTweet> tweets = new ArrayList<>(); public String getQuery() { return query; } public void setQuery(String query) { this.query = query; } public List<TweetQueryTweet> getTweets() { return tweets; } public void setTweets(List<TweetQueryTweet> tweets) { this.tweets = tweets; } public void addTweets(TweetQueryTweet... queryTweets) { for (TweetQueryTweet tweet : queryTweets) { this.tweets.add(tweet); } } @Override public String toString() { return String.format("[TweetQuery - query:%s, tweets:%s]",query, tweets); }
}
- 的客户端(的Arquillian)测试是与上述相同的
- 该泽西Post方法是与上述相同的
(un)marshall 的对象类是:
@XmlRootElement public class TweetClusters { List tweetClusters = new ArrayList<>();
public void addCluster(Cluster c) { TweetCluster tweetCluster = new TweetCluster(c); tweetClusters.add(tweetCluster); } public List<TweetCluster> getTweetClusters() { return tweetClusters; } public void setTweetClusters(List<TweetCluster> tweetClusters) { this.tweetClusters = tweetClusters; } @Override public String toString() { return String.format("[TweetClusters:%s]", tweetClusters); }
}
public class TweetCluster { List labels = new ArrayList<>(); 列表文档 = 新的 ArrayList<>();
public TweetCluster() { } public TweetCluster(Cluster c) { labels.add(c.getLabel()); for (Document doc : c.getDocuments()) { docs.add(doc.getTitle()); } } public List<String> getLabels() { return labels; } public void setLabels(List<String> labels) { this.labels = labels; } public List<String> getDocs() { return docs; } public void setDocs(List<String> docs) { this.docs = docs; } @Override public String toString() { return String.format("[TweetCluster - labels: %s, docs:%s]", labels, docs); }
}
公共类 TweetQuery { 字符串查询;
List<TweetQueryTweet> tweets = new ArrayList<>(); public String getQuery() { return query; } public void setQuery(String query) { this.query = query; } public List<TweetQueryTweet> getTweets() { return tweets; } public void setTweets(List<TweetQueryTweet> tweets) { this.tweets = tweets; } public void addTweets(TweetQueryTweet... queryTweets) { for (TweetQueryTweet tweet : queryTweets) { this.tweets.add(tweet); } } @Override public String toString() { return String.format("[TweetQuery - query:%s, tweets:%s]",query, tweets); }
}
(Arghhh, sorry about the formatting; I can't fix it in SO)
(啊,抱歉格式化;我无法在 SO 中修复它)
For debugging purposes it is often good to get back the string representation returned from the response (ie. XML or JSON) and you simply specify the entity type as String.class
:
出于调试目的,返回从响应(即 XML 或 JSON)返回的字符串表示通常很好,您只需将实体类型指定为String.class
:
String x = response.readEntity(String.class);
回答by Jason McD
I'm not sure why you have the models Annotated with @XmlRootElements. So I would think you could remove that and make sure you are using Hymanson to Serialize and Deserialize your request and response body. Which I assume you are or gson.
我不确定你为什么用@XmlRootElements 注释模型。所以我认为你可以删除它并确保你使用 Hymanson 来序列化和反序列化你的请求和响应正文。我假设你是或gson。
回答by abdellah7000
Try to return response like this : Response.ok(tweetClusters).build();
尝试像这样返回响应:Response.ok(tweetClusters).build();