Предоставление подмножества свойств bean-компонента в виде XML-ответа службы REST - PullRequest
2 голосов
/ 03 марта 2010

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

Допустим, у меня есть Java-бин с набором свойств:

public interface Customer {
    public String getFirstName();
    public String getLastName();
    public Address getAddress(); // embedded bean with its own properties
    ... // lots more
}

Очевидно, есть соответствующая реализация, плюс определены соответствующие установщики (хотя для некоторых свойств сеттеры могут не отображаться в интерфейсе).

Существует служба (интерфейс POJO + реализация), которая определяет набор операций, которые могут выполняться над клиентами (CRUD, некоторые запросы find () и т. Д.). Сервис загружается через Spring, и все работает нормально локально и через RMI.

Теперь у меня есть клиент (приложение для iPhone), которому требуется доступ к небольшому подмножеству функциональных возможностей, предоставляемых через вышеуказанный API - подмножество как с точки зрения операций службы, так и свойств API. Идея состоит в том, чтобы представить это подмножество через API в стиле REST:

GET /services/customers/1234

возвращает

<customer>
  <firstName>Homer</firstName>
  <lastName>Simpson</lastName>
  <city>Springfield</city>
</customer>

или, может быть, даже

<customer firstName="Homer" lastName="Simpson" city="Springfield" />

Вопрос в том, как мне это сделать? Я (кратко) посмотрел на JAXB / CXF / Jersey, и похоже, что мне нужно определить схему, сгенерировать на ее основе группу классов и скопировать данные из моих сущностей API в эти классы. Есть ли способ избежать всего этого?

В идеале я хотел бы аннотировать соответствующие свойства в моих объектах API и сделать так, чтобы они (и только они) были распределены "автоматически". Я в порядке с написанием специального интерфейса / реализации для конечной точки веб-службы, если это необходимо; аннотирование существующего было бы еще лучше.

Другой (более насущный) вопрос - я что-то делаю глупо? Есть ли более простой и / или лучший способ? В прошлый раз, когда я работал с веб-сервисами, Axis был 1,1 раза, а в прошлый раз, когда я работал с iPhone, никогда не было :-), поэтому любые указатели будут высоко оценены.

Обновление: Чтобы уточнить - я ищу самый простой способ упорядочить подмножество свойств javabean в XML (или, может быть, JSON?) без необходимость писать / генерировать дополнительный класс для представления указанного подмножества свойств. Приведенный выше пример является упрощением, в действительности API довольно обширный и включает в себя множество классов. Я действительно хочу избежать дублирования, если это возможно.

Ответы [ 3 ]

1 голос
/ 03 марта 2010

Googling jaxb interface , кажется, указывает на то, что с интерфейсами трудно работать в JAXB, как видно из этого сообщения в блоге java.net и другого stackoverflow .

Может быть проще, если ваш POJO - это класс, а не интерфейс. Я использую RESTEasy (другая реализация JAX-RS) с JAXB, и мне нужно только аннотировать мой класс POJO с помощью @XmlRootElement. С другой стороны, я написал собственный клиентский код http в marshall / unmarshall того же аннотированного класса с JAXB (это было бы автоматически при использовании клиентского прокси-сервера RESTEasy, если бы я мог это использовать). Обратите внимание, что у меня нет определенной схемы, но я могу многого избежать, так как я контролирую обе стороны веб-службы RESTful.

На Джерси есть клиентский API , на который вы, возможно, захотите взглянуть. CXF также имеет интерфейсный интерфейс / клиентский API , включающий механизм на основе прокси, аналогичный RESTEasy.

Взгляните на книгу RESTful Java с JAX-RS , которая охватывает следующее, что я считаю полезным:

  • Концепции обслуживания REST
  • обзор различных реализаций, включая поддержку клиентского API
  • примеры кода

Пример контроллера:

@GET
@Produces( { MediaType.APPLICATION_XML })
@Path("/customers/{id}")
public Customer getCustomer(@PathParam("id") int id) {
    ...
    return customer;
}

Пример POJO:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
  Address address;
  String name;

  // annotate with XmlTransient to prevent mapping this property/type to XML
  @XmlTransient
  String ssn;
  ...
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Address {
  String planet;
  ...
}

XmlTransient Java doc

0 голосов
/ 03 марта 2010

Самый простой способ сделать это: использовать API сериализации XML, такие как XStream или Simple, которые созданы специально для такого рода вопросов, которые вы задаете от POJO к XML. Выбрать подмножества и перейти к атрибутам очень просто:

class Customer {
    @XStreamAsAttribute
    String firstName;
    @XStreamAsAttribute
    String lastName;
    @XStreamOmitField
    Address address();
}
0 голосов
/ 03 марта 2010

Я бы предпочел аннотировать классы, которые у вас уже есть, с помощью аннотаций JAXB, и компилятор связывания должен создать схему на основе классов, которые у вас уже есть, запустив schemagen для аннотированных исходных файлов пример здесь .

Я обнаружил, что JAXB чрезвычайно полезен и относительно прост в использовании при создании схем из классов Java и классов Java из схем, которые я использую при создании веб-сервисов, используемых для обслуживания страховых полисов здесь, на работе.

...