2012-06-19 14 views
5

więc mam prostą usługę internetową:JAX-WS: Jak odpowiedź SOAP zwrócić obiekt 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; 
    } 

Klasa książka jest również prosta:

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

Teraz kiedy zadzwonić ten serwis internetowy w testerze przeglądarki, uzyskać:

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> 


Czy możliwe h ave wracającą HashMap obiekt pokazany na <return> tagu, coś

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

powód, dla którego chcę wartości w tagach w obie strony jest dlatego, ze strony klienta, używam jQuery AJAX na stronie internetowej, aby nazwać usługa sieci Web, a otrzymywany przeze mnie kod odpowiedzi to po prostu puste tagi <return>. Jak mogę uzyskać prawdziwą wartość książki od strony klienta AJAX?

Oto mój kod AJAX internetowej:

$.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 
    } 
} 

testowałem z prostego Hello World usługi internetowej i to działało.

+0

Odpowiedź brzmi "to zależy" :) Najlepiej jest odpalić swoje ulubione IDE (może Eclipse J2EE, może coś jeszcze), zakodować mały interfejs Java, nacisnąć przycisk "przekonwertuj na WSDL" ... i zobacz, co się stanie. Następnie, jeśli nie ma barf ... zobacz, czy wynikowy WSDL jest czymś, czego możesz użyć ze wszystkimi klientami (być może Axis, być może Axis2, być może .Net, może coś zupełnie innego). Powodzenia! – paulsm4

+0

id = 1 - jest identyfikatorem z książki klasy lub Integer z HashMap? – Ilya

+0

id jest z klasy. Nie wiem dokładnie, jak powinna wyglądać odpowiedź xml. ale chciałbym, aby te pola instancji w obiekcie książki były wyświetlane w tagach zwracanych. – neo

Odpowiedz

3

Aby pomóc JAXB, można „owinąć” twojej HashMap w klasie i używać @XmlJavaTypeAdapter aby dokonać niestandardowej serializacji mapy na 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; 
    } 

} 

Następnie użyj tej klasy jako wartości zwracanej swoimi 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; 
    } 

mimo wszystko, trzeba wdrożyć adapter MapAdapter. Jest na to kilka sposobów, więc polecam sprawdzenie: this

2

JAX-WS Jak SOAP Response powrócić HashMap obiekt

Należy nie wystawiać żadnych Java specyficzne konstrukcje jak HashMap poprzez Web Service.
Web Services to około interoperacyjność, a podążanie za ścieżkami takimi jak Twoja jest niewłaściwe.
Wystarczy powrócić wymagane informacje tak, że klient usługi internetowej można zbudować tabeli mieszania niezależnie od języka programowania jest napisane

+0

Twoja sugestia jest bardzo niejasna. Proszę opracować lub edytować "wymagane informacje". Będę głosować jako nieprzydatny, dopóki nie dostarczysz lepszej odpowiedzi. Dzięki! –

+1

@ Paul-SebastianManole: Nie mam pojęcia o czym mówisz. Myślę, że oświadczenie jest całkiem jasne. – Cratylus

+0

Cóż, to nie ma dla mnie większego sensu. Mam na myśli, OK, nie wiem zbyt wiele o JAX-WS, ale zwracam "konstrukcje" Javy jak proste obiekty i kolekcje. JAXB wykonuje swoją pracę. Po przeczytaniu nieco więcej w tym tygodniu zdałem sobie sprawę, że być może będę musiał stworzyć określone typy klas z poprawnymi adnotacjami, aby JAXB mógł przekonwertować na odpowiedni XML. Czy mam rację czy się mylę? Tym razem proszę podać więcej wyjaśnień, także w odniesieniu do tego, co miałeś na myśli w odpowiedzi, "wymagane informacje, aby klient usługi internetowej mógł zbudować tabelę mieszającą, niezależnie od języka programowania, w którym został napisany". –

1

Na JBoss Forum znalazłem rozwiązanie, które działa dla mnie na Glassfish. Oryginalne rozwiązanie to JBoss Forum, topic from Allesio Soldano. Składa się z jednej klasy pomocniczej, która ma HashMap jako typ zagnieżdżony, tj. HashMap<String, String>. Następnie w klasie usług internetowych ta klasa pomocnicza jest używana jako wartość zwracana. Adnotacja @XmlAccessorType(XmlAccessType.FIELD) zapewnia, że ​​ta struktura będzie poprawnie traktowana przez SOAP w odpowiedzi SOAP.

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

W Webservice użyj tej klasy bezpośrednio jako obiektu powrotu bez żadnych dodatkowych ustawień. Oczywiście obiekt musi najpierw zostać utworzony, a mapa powinna być wypełniona podobnie jak w innym POJO.

Jeśli HashMap składa się z innych nie-prymitywnych typów (obiektów), udowodniłem, że można rekursywnie używać tego samego sposobu na zagnieżdżonych złożonych obiektach. Reguła jest taka, że ​​ta klasa nie jest dziedziczona, tzn. Musi być zagnieżdżona jako atrybut, a ostatnia klasa ma wszystkie atrybuty prymitywne.

Powiązane problemy