Я написал базовую услугу RESTful, использующую Java/Jersey для управления подписчиками, и теперь я пытаюсь создать клиента для разговора к этой службе, но я получаю ошибку во время выполнения, которую я не понимаю. Вот урезана версия, которая имеет проблему:Использование Джерси для POST для обслуживания - «Писатель тела сообщения ... не найден»
Класс Subscriber:
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Subscriber {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Subscriber() {
}
}
Основное испытание приложение:
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
public class MyTestClient {
public static void main(String[] args) {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(UriBuilder.fromUri("http://localhost:8080/MyService").build());
Subscriber s = new Subscriber() {{
setFirstName("John");
setLastName("Doe");
}};
System.out.println(service.path("subscriber")
.type(MediaType.APPLICATION_XML)
.entity(s)
.post(String.class));
}
}
И я получаю эту ошибку:
Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: com.sun.jersey.api.client.ClientHandlerException: A message body writer for Java type, class MyTestClient$1, and MIME media type, application/xml, was not found
Пришло неясно, для чего именно это сообщение об ошибке; это похоже на преобразование подписчика в XML (хотя для меня сообщение об ошибке подразумевает, что оно пытается конвертировать MyTestClient, что не может быть прав ...) Я использовал тот же класс Subscriber в мой сервис, и у него нет проблем с созданием XML для отправки клиенту, поэтому я довольно смущен.
Если я заменю объект Subscriber на строку, содержащую XML, я не получаю сообщение об ошибке, но я хочу использовать объекты по многим причинам.
В чем причина этого сообщения об ошибке и как его исправить?
EDIT: Для справки, хотя я не уверен, что это отношение, вот соответствующая часть стороны обслуживания кода:
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Subscriber post(Subscriber subscriber) {
/// doesn't get here
}
Кроме того, это работает, но не с помощью объекта подписчика:
String xml = "<subscriber><firstName>John</firstName><lastName>Doe</lastName></subscriber>";
System.out.println(service.path("subscriber")
.type(MediaType.APPLICATION_XML)
.entity(xml)
.post(String.class));
UPDATE: я могу обойти эту проблему путем явного преобразования моего объекта в StrI в первую очередь, таким образом:
JAXBContext context = JAXBContext.newInstance(Subscriber.class);
Marshaller m = context.createMarshaller();
StringWriter sw = new StringWriter();
m.marshal(s, sw);
String xml = sw.toString();
System.out.println(service.path("subscriber")
.type(MediaType.APPLICATION_XML)
.entity(xml)
.post(String.class));
но это довольно грязно, и я не понимаю, зачем это необходимо.
Насколько я могу судить, аргумент String.class указывает тип ответа, а не запрос. post (s) (без части .entity()) приводит к той же ошибке. Даже если бы это сработало, это не было бы слишком полезно, потому что этот вариант сообщения имеет пустоту, поэтому я не мог получить ответ. –
жаль, что вы правы, я подпрыгнул до конца, заметив это различие в ваших двух частях кода. Я уточню свой ответ с моим следующим предложением. – TheArchitect
Aha! Мне было интересно, что такое MyTestClient $ 1. Я не думал о том, что используемая нотация подписи подписчика, которую я использовал, создает анонимный подкласс (я больше привык к C#, где аналогичная нотация используется для инициализации объекта без построения подкласса). Благодаря! –