Как сгенерировать XML-ответ из классов с помощью общих шаблонов (‹T›) в RESTEasy?

У меня есть общий класс ServiceResponse следующим образом:

@XMLRootElement
public class ServiceResponse<T>
{
    private T data;
    private String error;
    //setters n getters

}

Из моей службы RESTEasy я хочу сгенерировать ответ xml как:

List<Customer> customers = someDAO.getCustomers();
ServiceResponse<List<Customer>> resp = new ServiceResponse<List<Customer>>();
resp.setData(customers);
resp.setError("No Error");
return resp;
or return Response.ok().entity(resp).build();

Но это ошибка, так как нет JaxbMarshallWriter для java.util.List.

Я могу упорядочить список, используя класс GenericEntity.

GenericEntity<List<Customer>> entity = new GenericEntity<List<Customer>>(customers){};
Response.ok(entity).build();

Но GenericEntity<ServiceResponse<List<Customer>>> не работает, говоря, что нет JaxbMarshallWriter для java.util.List.

Есть ли какой-нибудь обходной путь для упорядочения/неупорядочения классов с помощью общих шаблонов (, )?


person K. Siva Prasad Reddy    schedule 25.05.2012    source источник
comment
может это поможет? stackoverflow.com/ вопросы/5391486/   -  person Friso    schedule 26.10.2012


Ответы (4)


Я не уверен, имеет ли значение, что ваш класс использует общие шаблоны, но именно так я бы сгенерировал ответ XML с помощью RESTEasy.

Это класс, который будет содержать ответ вашего сервиса

public class ServiceResponse<T>
{
    private T data;
    private String error;
    //setters n getters
}

Это класс, который на самом деле преобразует ваш ответ в XML. Этот класс на самом деле не делает ничего, кроме как принимает и создает XML/JSON или что-то еще, что вы используете. Затем он передает запрос классу, который выполняет реальную работу. Однако это класс, который ответит на ваш конкретный вопрос (я полагаю).

@Path("/myrestservice")
public class SomeRestService
{
    private SomeCoreService coreService;
    //getters and setters here

    @POST
    @Path("/examples/")
    @Consumes({MediaType.APPLICATION_XML}) //this consumes XML
    @Produces({MediaType.APPLICATION_XML}) //this produces XML
    public ServiceResponse<T> exampleFunction(Request request)
    {
        try
        {
            //Unwrap the request and take only what you need out
            //of the request object here
            return this.coreService.examples(request.getStringFromRequest());
        }
        catch(Exception ex)
        {
            return new ServiceResponse<T>(Put response error message here);
        }
    }
}

Это класс, который делает всю реальную работу.

public class SomeCoreService
{
    public ServiceResponse<T> examples(String stringFromRequest)
    {
        //do whatever work you need to do here.
        return new ServiceResponse<T>(put whatever you need in the service response here)
    }
}

Кроме того, я ничего из этого не тестировал. Надеюсь, этого достаточно для вас, чтобы получить образец.

person j.jerrod.taylor    schedule 08.03.2013

Проблема не в универсальном, проблема в том, что вы должны обернуть свой список внутри объекта.

ServiceResponse<ResponseData<Customer>> resp = new ServiceResponse<ResponseData<Customer>>();

Затем вы можете аннотировать класс ResponseData для представления набора объектов.

person minus    schedule 02.12.2012

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

Вот мой пример, если он может быть вам полезен:

package com.dosideals.server.beans;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author LOTFI
 */
@Entity
@XmlRootElement
public class Admin implements Serializable {

    @Id
    private String login;
    private String password;
    private String firstName;
    private String lastName;

    public Admin() {
    }

    public Admin(String login, String password, String firstName, String lastName) {
        this.login = login;
        this.password = password;
        this.firstName = firstName;
        this.lastName = 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 String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Admin other = (Admin) obj;
        if ((this.login == null) ? (other.login != null) : !this.login.equals(other.login)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 83 * hash + (this.login != null ? this.login.hashCode() : 0);
        return hash;
    }

    @Override
    public String toString() {
        return "Admin{" + "login=" + login + ", password=" + password + ", firstName=" + firstName + ", lastName=" + lastName + '}';
    }
}

А это контейнер AdminContainer :

package com.dosideals.server.beans.containers;

import com.dosideals.server.beans.Admin;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author LOTFI
 */
@XmlRootElement
public class AdminContainer {

    private List<Admin> admin;

    public AdminContainer() {
    }

    public AdminContainer(List<Admin> admin) {
        this.admin = admin;
    }

    public List<Admin> getAdmin() {
        return admin;
    }

    public void setAdmin(List<Admin> admin) {
        this.admin = admin;
    }
}
person Lotfiction    schedule 12.02.2013

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

Проблема в том, что когда у вас есть общий класс, скажем, MyClass jaxB, за исключением того, что T аннотируется либо @XMLRootElement, либо @XMLType.

в вашем сценарии кода ваш тип T относится к списку Список не имеет ни одного из @XMLRootElement или @XMLType, поэтому он выдает ошибку. Я думаю, что решение для вышеуказанного случая - создать класс-оболочку для коллекции, например

@XMLRootElement
Class JaxBCollection<T>{
    java.util.Collection<T> collection;
    /* Have getters and setters*/
}

теперь в вашем коде есть что-то вроде этого.

List<Customer> customers = someDAO.getCustomers();
JaxBCollection<Customer> jaxBCustomers= new JaxBCollection<Customer>();
jaxBCustomers.setCollection(customers);
ServiceResponse<JaxBCollection<Customer>> resp = new ServiceResponse<JaxBCollection<Customer>>();
resp.setData(jaxBCustomers);
resp.setError("No Error");
return resp;
person rahul maindargi    schedule 20.04.2013