среда, 11 сентября 2013 г.

Generate a JAX-WS Web Service Client

Вот уже долгое время в качестве клиента для веб-сервисов использую самый простой Axis, и этого вполне хватало, однако столкнулся с проблемой что JAX-WS веб-сервис, возвращающий массив своих объектов перестал правильно "распознаваться" axis'овским клиентом.
AxisFault!
Все таки, для JAX-WS сервиса требуется и jAX-WS клиент!

Eclipse FAQ рекомендует для этого использовать фреймворк CXF:
Generate a JAX-WS Web Service Client from a WSDL document using Apache CXF
однако, вовсе необязательно использовать тяжелый фреймворк для этого, можно решить проблему проще:

1) Сгенерировать при попощи wsimport:

wsimport -s src/ -d bin/ SeaIntService.wsdl

В качестве wsdl location можно прямо указать url, но в моем случае была переброска портов и адрес endpoint'а отличался от прописанного в wsdl, поэтому я скачивал wsdl заранее:

wget http://sea:9084/SeaIntService/SeaIntService/SeaIntService.wsdl
wget http://sea:9084/SeaIntService/SeaIntService/SeaIntService_schema1.xsd

2) Скрипт ant:
    <taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
        <classpath>
            <pathelement location="jaxws/jaxws-tools.jar" />
        </classpath>
    </taskdef>

...

    <target depends="clean, init" name="generate-JAX-WS-client" description="Generates JAX-WS files from the wsdl files">
        <get src="http://sea:9084/SeaIntService/SeaIntService/SeaIntService.wsdl" dest="" />
        <get src="http://sea:9084/SeaIntService/SeaIntService/SeaIntService_schema1.xsd" dest="" />
        <delete dir="${basedir}/src/com/sitronics/ws" />
        <wsimport debug="true" 
            xendorsed="true" 
            verbose="${verbose}" 
            keep="true" 
            sourcedestdir="${basedir}/src"
            destdir="${basedir}/bin" 
            package="com.sitronics.ws" 
            wsdl="${wsdl.dir}/SeaIntService.wsdl"
            target = "2.0"    >
        </wsimport>
    </target>

По той же причине я сперва скачиваю wsdl, а уже потом запускаю wsimport.
Для com.sun.tools.ws.ant.WsImport потребуется jax-ws фреймворк (jaxws-tools.jar), я взял его с https://jax-ws.java.net

Вот и все!

String url = "http://sea:9084/SeaIntService/SeaIntService";


URL wsdlLocation = new URL(url.concat("/SeaIntService.wsdl"));
QName qname = new QName("http://ws.sitronics.com/", "SeaIntService");

SeaIntService service = new SeaIntService(wsdlLocation, qname);
SeaInt seaInt = service.getSeaIntPort();

// Use the BindingProvider's context to set the endpoint
BindingProvider bp = (BindingProvider) seaInt;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);

List<PdfDocument> pdfs = seaInt.getPdfDocuments("{D3ED8387-1A95-4032-9B20-0216ADA310EE}");
 
Update (11.11.2013):
maven sample:





    4.0.0
    org.jvnet.jax-ws-commons
    mojo.it.Chebiwebservices
    1.0-SNAPSHOT
    
    Chebiwebservices

    
        UTF-8
        2.3
        2.2.8
    

    
        
            com.sun.xml.ws
            jaxws-rt
            ${jaxws-ri.version}
        
    

    
        
            
                maven-compiler-plugin
                2.3.2
                
                    1.5
                    1.5
                
            
            
                org.jvnet.jax-ws-commons
                jaxws-maven-plugin
                ${jaxws.plugin.version}
                
                    
                        
                            wsimport
                        
                        
                            
                                http://www.ebi.ac.uk/webservices/chebi/2.0/webservice?wsdl
                            
                            
                            false
                        
                    
                
            
        
    


Источник:
https://java.net/projects/jax-ws-commons/sources/svn/show

7 комментариев:

  1. Согласен, что для создания клиентской части качать ничего не нужно - всё что нужно есть в составе JRE.

    На стороне сервера Apache CXF хорош, со Spring просто интегрируется.


    Пара вопросов
    1) SeaIntService_schema1.xsd на каком этапе используется и используется ли вообще?

    Когда я помнится генерировал в наличии был только wsdl файл.


    2) точно нужно что-то качать с jax-ws.java.net - это JAX-WS Reference Implementation - поставляемая с Oracle JDK (чуть более старая версия и не все классы)

    стандартный wsimport работает без скачиваний

    ОтветитьУдалить
    Ответы
    1. CXF смотрел, даже первые версии веб-сервисов на нем выпускал, однако по какой-то причине CXF-ные веб-сервисы у меня на WebSphere разворачивались ну очень долго. Долго - это 30 минут. Какой-то глюк. Может исправили уже.

      В xsd у меня веб-сервис хранит описания типов.

      Типа:
      < xs:complexType name="getPdfDocuments">
      < xs:sequence>
      < xs:element name="id" type="xs:string" minOccurs="0"/>
      < xs:element name="xml" type="xs:string" minOccurs="0"/>
      < /xs:sequence>
      < /xs:complexType>

      Не думаю что без него получится сгенерировать клиента.
      Проверю.
      Нет, без него никак.
      [WARNING] schema_reference.4: Failed to read schema document 'SeaIntService_schema1.xsd', because 1) could not find the document;
      Может другие фреймворки веб-сервисов помещают описания сразу в WSDL?

      2) Да, тоже обратил внимание.
      Но, "что-то нужно" - это для антовского таска com.sun.tools.ws.ant.WsImport
      Т.е. для wsimport.bat - ничего не нужно, для анта - качай jar-ки!
      В JRE его нет.

      Удалить
    2. Попробуй?

      Вот короткий туториал http://www.java-forums.org/blogs/web-service/1145-how-create-java-web-service.html

      не требует ничего кроме JDK т.е. никаких app servers/servlet containers

      Удалить
    3. Сам попробовал - ларчик просто открывался.
      В wsdl файле идёт ссылка на xsd





      Удалить
    4. Кстати, как выяснилось, таскать с собой клиентскую часть jaxws не только не нужно, но и вредно!
      Разрабатывал пол jre7, все было ок, а проверив на клиенте jre6 натолкнулся на
      java.lang.NoSuchMethodError: javax.xml.ws.WebFault.messageName()Ljava/lang/String;
      Объяснение тут: http://stackoverflow.com/questions/12631002/jax-ws-2-2-and-jdk6-with-maven
      Подумал, а нафига я тащу зависимости jaxws 2.0 в maven pom.xml, они же в jre есть и убрал их!

      Удалить
  2. >Попробуй?

    Я примерно так сейчас и создаю веб-сервисы.
    Только вместо встроенного web servicve explorer я бы рекомендовал использовать SoapUI.

    ОтветитьУдалить