如何在RESTEasy中使用通用模板(<t>)从类生成XML响应?</t>

时间:2012-05-25 11:47:18

标签: java web-services rest jaxb 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();

但由于java.util.List没有JaxbMarshallWriter,因此抛出错误。

我可以编组列表使用GenericEntity类。

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

但是GenericEntity<ServiceResponse<List<Customer>>>没有说java.util.List没有JaxbMarshallWriter。

是否有任何解决方法可以使用通用模板(,)来编组/解组类?

4 个答案:

答案 0 :(得分:1)

我不确定你的类是否使用通用模板会有所不同,但这就是我使用RESTEasy生成XML响应的方法

这是保留服务响应的类

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)
    }
}

另外,我还没有测试过这些。希望这足以让你获得模式。

答案 1 :(得分:0)

问题不在于泛型问题在于你应该将列表包装在一个对象中。

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

然后,您可以注释ResponseData类来表示一组对象。

答案 2 :(得分:0)

我为同一个问题做过的解决方案是创建一个新类型来模拟泛型类型List,就像我一样,我创建了一个名为Container的新类型(例如:PersonContainer),其中有一个我的实体(Person)的列表,我使用它而不是List类型,它工作得很好......

这里有你的例子,如果它对你有用:

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;
    }
}

答案 3 :(得分:0)

我知道很晚才回复,但由于没有投票的答案我会尽力给出答案希望它有所帮助。

问题是当你有一个泛型类时说MyClass jaxB除了T用@XMLRootElement或@XMLType注释。

在你的代码场景中你的类型T是列表列表没有任何@XMLRootElement或@XMLType所以它会抛出错误。 我认为上述案例的解决方案是为Collection创建一个包装类,如

@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;