2012-05-25 11 views
9

Ho una classe ServiceResponse generica come segue:Come generare la risposta XML da classi con modelli generici (<T>) in RESTEasy?

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

} 

Dal mio servizio RESTEasy, voglio generare risposta XML come:

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(); 

Ma questo è errore di lancio in quanto non v'è alcuna JaxbMarshallWriter per Java .util.List.

Sono in grado di elencare Elenco di classi GenericEntity.

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

Ma GenericEntity<ServiceResponse<List<Customer>>> non funziona a dire di no JaxbMarshallWriter per java.util.List.

C'è qualche problema con le classi marshall/unmarshall con modelli generici (,)?

+0

forse questo aiuta? http://stackoverflow.com/questions/5391486/make-a-collection-generic-in-javax-xml-bind – Friso

risposta

0

Il problema non è il generico il problema è che è necessario avvolgere l'elenco all'interno di un oggetto.

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

È quindi possibile annotare la classe ResponseData per rappresentare un insieme di oggetti.

0

Una soluzione che avevo fatto per lo stesso problema, era la creazione di un nuovo tipo per simulare il tipo generico Elenco, come avevo fatto, ho creato un nuovo tipo che ho chiamato Container (ad esempio: PersonContainer) in che c'è una lista del mio soggetto (persona), che io uso invece che il tipo list, e funziona molto bene ...

Qui avete il mio esempio se può essere utile per voi:

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

E questo è il contenitore 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; 
    } 
} 
1

non sono sicuro se fa la differenza che la classe utilizza i modelli generici, ma questo è come vorrei generare una risposta XML utilizzando RESTEasy

Questa è la classe che avrebbe tenere la risposta del servizio

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

Questa è la classe che trasformerebbe la tua risposta in XML. Questa classe in realtà non fa molto altro che prendere e produrre XML/JSON o qualsiasi altra cosa tu stia usando. Passa quindi la richiesta alla classe che fa il vero lavoro. Questa è comunque la classe che risponderebbe alla tua domanda specifica (credo).

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

Questa è la classe che fa tutto il vero lavoro.

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

Inoltre, non ho provato nulla di tutto questo. Speriamo che sia abbastanza per voi per ottenere il modello.

0

So molto in ritardo per rispondere ma poiché non c'è risposta votata cercherò di dare la mia risposta spero che aiuti.

Il problema è quando una classe generica dice MyClass eccezioni jaxB T è annotato con @XMLRootElement o @XMLType.

nello scenario del codice il tipo T di Elenco elenco non dispone di @XMLRootElement o @XMLType, pertanto genera un errore. Penso che la soluzione per il caso di cui sopra è di creare una classe wrapper per la raccolta come

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

ora nel codice avere qualcosa di simile.

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; 
Problemi correlati