2012-06-19 5 views
5

Così ho un semplice servizio web:JAX-WS: come dare una risposta SOAP restituisce un oggetto HashMap

@WebMethod(operationName="getBookList") 
    public HashMap<Integer,Book> getBookList() 
    { 
     HashMap<Integer, Book> books = new HashMap<Integer,Book>(); 
     Book b1 = new Book(1,"title1"); 
     Book b2 = new Book(2, "title2"); 
     books.put(1, b1); 
     books.put(2, b2); 
     return books; 
    } 

La classe libro è anche semplice:

public class Book 
{ 
    private int id; 
    private String title; 

    public int getId() 
    { 
     return id; 
    } 

    public String getTitle() 
    { 
     return title; 
    } 
    public Book(int id, String title) 
    { 
     id = this.id; 
     title = this.title; 
    } 
} 

Ora quando si chiama questo servizio nella tester del browser, ottengo:

Method returned 
my.ws.HashMap : "[email protected]" 

SOAP Request 
    ... 
    ... 

SOAP Response 

<?xml version="1.0" encoding="UTF-8"?> 
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> 
    <S:Body> 
     <ns2:getBookListResponse xmlns:ns2="http://ws.my/"> 
      <return/> 
     </ns2:getBookListResponse> 
    </S:Body> 
</S:Envelope> 


E 'possibile h ave restituita HashMap oggetto mostrato in <return> tag, qualcosa come

<return> 
    <Book1> 
      id=1 
      title=title1 
    </Book1> 
</return> 
<return> 
    <Book2> 
      id=2 
      title=title2 
    </Book2> 
</return> 

La ragione per cui voglio i valori nei tag di ritorno è perché, dal lato client, sto usando jQuery AJAX in una pagina web per chiamare questo servizio web, e la risposta XML che sto ottenendo è solo tag <return> vuoto. Come faccio a ottenere il valore reale del libro dal lato client AJAX?

Ecco il mio codice AJAX web:

$.ajax({ 
     url: myUrl, //the web service url 
     type: "POST", 
     dataType: "xml", 
     data: soapMessage, //the soap message. 
     complete: showMe,contentType: "text/xml; charset=\"utf-8\""   

    }); 
function showMe(xmlHttpRequest, status) 
{ (xmlHttpRequest.responseXML).find('return').each(function() 
    { // do something 
    } 
} 

ho provato con semplice servizio web ciao mondo e ha funzionato.

+0

La risposta è "dipende" :) La soluzione migliore è lanciare il tuo IDE preferito (forse Eclipse J2EE, forse qualcos'altro), creare una piccola interfaccia Java, premere il pulsante "converti in WSDL" ... e vedi cosa succede Quindi, se non funziona, vedi se il WSDL risultante è qualcosa che puoi usare con tutti i tuoi client (forse Axis, forse Axis2, forse .Net, forse qualcos'altro interamente). In bocca al lupo! – paulsm4

+0

id = 1 - ID del class book o Integer di HashMap? L'ID – Ilya

+0

proviene dal libro di classe. Non so esattamente come dovrebbe essere la risposta xml. ma mi piacerebbe che quei campi di istanza nell'oggetto del libro fossero mostrati nei tag di ritorno. – neo

risposta

3

Al fine di aiutare JAXB, si puo 'avvolgere' il tuo HashMap in una classe e utilizzare il @XmlJavaTypeAdapter per rendere la serializzazione personalizzata della mappa in XML.

public class Response { 

    @XmlJavaTypeAdapter(MapAdapter.class)  
    HashMap<Integer, Book> books; 

    public HashMap<Integer, Book> getBooks() { 
     return mapProperty; 
    } 

    public void setBooks(HashMap<Integer, Book> map) { 
     this.mapProperty = map; 
    } 

} 

Quindi utilizzare questa classe come un valore di ritorno della vostra WebMethod

@WebMethod(operationName="getBookList") 
    public Response getBookList() 
    { 
     HashMap<Integer, Book> books = new HashMap<Integer,Book>(); 
     Book b1 = new Book(1,"title1"); 
     Book b2 = new Book(2, "title2"); 
     books.put(1, b1); 
     books.put(2, b2); 
     Response resp = new Response(); 
     resp.setBooks(books); 
     return resp; 
    } 

Dopo tutto, è necessario implementare l'adattatore MapAdapter. Ci sono diversi modi per farlo, quindi ti consiglio di controllare this

2

JAX-WS Come fare tornare risposta SOAP hashmap oggetto

Si dovrebbe Non esporre alcun costrutti specifici Java come HashMap tramite un Web Service.
I servizi Web sono circa l'interoperabilità e seguire percorsi come il tuo è sbagliato.
Basta restituire le informazioni richieste in modo che il client del servizio Web può costruire la tabella hash a prescindere dal linguaggio di programmazione è scritto

+0

Il tuo suggerimento è molto vago. Si prega di elaborare o modificare su "le informazioni richieste". Voterò come non utile fino a quando non sarà possibile fornire una risposta migliore. Grazie! –

+1

@ Paul-SebastianManole: Non ho idea di cosa stai parlando. Penso che la dichiarazione sia abbastanza chiara. – Cratylus

+0

Beh, per me non ha senso. Voglio dire, OK, non so molto su JAX-WS ma restituire "costrutti" di Java come oggetti semplici e opere di collezioni. JAXB fa il suo lavoro. Dopo aver letto un po 'di più questa settimana, ho capito che potrei aver bisogno di creare specifici tipi di classe con annotazioni corrette per JAXB da convertire in XML corretto. Ho ragione o sbaglio? E per favore fornisci ulteriori spiegazioni questa volta, anche riguardo a cosa intendevi nella tua risposta con "le informazioni richieste in modo che il client del servizio web possa costruire la tabella hash indipendentemente dal linguaggio di programmazione che è stato scritto". –

1

Su JBoss Forum ho trovato una soluzione, che funziona per me su Glassfish. La soluzione originale è JBoss Forum, topic from Allesio Soldano. Consiste in una classe ausiliaria, che ha una HashMap come tipo annidato, ad esempio HashMap<String, String>. Rispetto al servizio web Class questa classe ausiliaria viene utilizzata come valore di ritorno. L'annotazione @XmlAccessorType(XmlAccessType.FIELD) garantisce che tale struttura verrà adeguatamente trattata da SOAP in SOAP Response.

@XmlAccessorType(XmlAccessType.FIELD) 
public class MyHash { 
    protected HashMap<String,String> realMap; 

    // constructor 
    public MyHash() { 
    realMap = new HashMap<String,String>(); 
    } 

    /** 
    * @return HashMap<String,String> 
    */ 
    public HashMap<String,String> getRealMap() { 
    if (realMap==null) { 
     realMap = new HashMap<String,String>(); 
    } 
    return realMap; 
    } 

    /** 
    * @param key 
    * @param value 
    */ 
    public void put(String key, String value) { 
    realMap.put(key, value); 
    } 
} 

In Webservice utilizzare questa classe direttamente come oggetto di reso senza impostazioni aggiuntive. Ovviamente, l'oggetto deve essere prima creato e la mappa deve essere compilata in modo simile a un altro POJO.

Se HashMap è costituito da altri tipi (oggetti) non primitivi, ho provato che è possibile ricorsivamente utilizzare la stessa maniera sugli oggetti complessi nidificati. La regola è che quella classe non è ereditata, cioè deve essere annidata come attributo e l'ultima classe ha tutti gli attributi primitivi.

Problemi correlati