2013-06-10 2 views
0

Я написал базовую услугу 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)); 

но это довольно грязно, и я не понимаю, зачем это необходимо.

ответ

1

Ошибка "Писатель тело сообщения для типа Java, класс MyTestClient $ 1" сообщает, что он пытается выстроить анонимный внутренний класс. Обычно мы ожидаем увидеть «подписчика класса». Вероятно, вы теряете аннотации JAXB при выполнении этого нового Абонента() {{}}.

Моя первая рекомендация состояла в том, чтобы передать имя конструктору, который был бы чище и не освободил бы вас от аннотаций JAXB.

Subscriber s = new Subscriber("John","Doe"); 

или же вызывать конструктор по умолчанию, а затем установите поля впоследствии:

Subscriber s = new Subscriber(); 
s.setFirstName("John"); 
s.setLastName("Doe"); 

Если вам нужно определить анонимный внутренний класс, то вы можете попробовать reannotate @XmlRootElement до вашего нового анонимного класса определение. (никогда не пробовал, хотя ваш пробег может меняться :)

+0

Насколько я могу судить, аргумент String.class указывает тип ответа, а не запрос. post (s) (без части .entity()) приводит к той же ошибке. Даже если бы это сработало, это не было бы слишком полезно, потому что этот вариант сообщения имеет пустоту, поэтому я не мог получить ответ. –

+0

жаль, что вы правы, я подпрыгнул до конца, заметив это различие в ваших двух частях кода. Я уточню свой ответ с моим следующим предложением. – TheArchitect

+0

Aha! Мне было интересно, что такое MyTestClient $ 1. Я не думал о том, что используемая нотация подписи подписчика, которую я использовал, создает анонимный подкласс (я больше привык к C#, где аналогичная нотация используется для инициализации объекта без построения подкласса). Благодаря! –

0

Там может быть две проблемы:

  1. Убедитесь аннотацию истребляют установлен на верхней части REST веб-метод обслуживания обработки этого запроса: @Consumes (MediaType.APPLICATION_XML)

  2. Во-вторых СВОЙ bean, кажется, не хватает аннотации на геттеры. Вот ваш udpated боб:

@XmlRootElement общественного класса подписчика {

private String firstName; 
private String lastName; 

@XmlElement (name = "firstName") 
public String getFirstName() { 
    return firstName; 
} 

public void setFirstName(String firstName) { 
    this.firstName = firstName; 
} 

@XmlElement (name = "lastName") 
public String getLastName() { 
    return lastName; 
} 

public void setLastName(String lastName) { 
    this.lastName = lastName; 
} 

public Subscriber() { 
} 

}

+0

Аннотации \ @XmlElement не имеют значения. Класс отлично сериализуется в XML с помощью сервиса без этих аннотаций - это проблема только у клиента. Служба уже имеет соответствующую аннотацию \ @Consumes. Кроме того, как указано в моем вопросе, если я заменю объект-подписчик на String, содержащий XML, служба правильно ответит на него. Добавлен соответствующий бит службы на мой вопрос в качестве ссылки. –

Смежные вопросы