Apache CXF + Spring: создание простого клиента

Я начал изучать Apache CXF с помощью Spring. Прежде всего, я попытался создать простую модель клиент/сервер.

На стороне сервера: service.HelloWorld.java

@WebService
public interface HelloWorld {
  String sayHi(String text);
}

service.HelloWorldImpl.java

@WebService(endpointInterface = "service.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
   public String sayHi(String text) {
     return "Hello, " + text;
   }
}

Клиентская сторона: client.Client.java public class Client {

    public static void main(String[] args) {
          ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new  String[] {"cxf-client-servlet.xml"});
          HelloWorld client = (HelloWorld) context.getBean("client");
          System.out.println(client.sayHi("Batman"));
    }
}

cxf-client-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://cxf.apache.org/jaxws
    http://cxf.apache.org/schema/jaxws.xsd">

<bean id="client" class="service.HelloWorld" factory-bean="clientFactory" factory-method="create"/>

<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
    <property name="serviceClass" value="service.HelloWorld"/>
    <property name="address" value="http://localhost:8080/services/HelloWorld"/>
</bean>

The problem is: to make the client work I've had to add service.HelloWorld (package + interface) to the clients's project. I've heard that before using a service I need to generate a stub. So it's confusing for me. So that, what is the correct approach and what is the best practice (may be it is better to use some contract-first approach or suchlike)? Later, I want to add WS-Security, so I need a strong background =)

Заранее спасибо.


person Dmitry    schedule 27.01.2012    source источник


Ответы (2)


Если вы занимаетесь разработкой WS в первую очередь с кодом, то можно распространять интерфейс и отдавать его клиенту. Я считаю, что @WebService не нужен (?) в интерфейсе (только реализация), поэтому у клиента нет зависимостей от этой аннотации.

Даже если вы создаете веб-службы, ориентированные на код, вы все равно можете загрузить документ WSDL, созданный для вас с помощью Apache CXF, и вместо этого передать его клиенту. При таком подходе (который считается более зрелым, не говоря уже о том, что его можно использовать на разных платформах, таких как .NET) клиент должен генерировать заглушки (используя такой инструмент, как wsdl2java). Этот процесс автоматически создаст очень похожий клиентский интерфейс.

Это одна из причин, по которой так много людей предпочитают разработку по контракту — один и тот же WSDL используется для создания заглушек на стороне клиента и реализации WS на стороне сервера. Это ограничивает объем (случайных) несовместимостей.

person Tomasz Nurkiewicz    schedule 27.01.2012
comment
Спасибо за ответ. Как служба может распространять интерфейс? - person Dmitry; 27.01.2012
comment
Итак, вы предлагаете не использовать JaxWsProxyFactoryBean? - person Dmitry; 27.01.2012
comment
Нужна аннотация @WebService - я проверил =) - person Dmitry; 27.01.2012
comment
@Dmitry: вы можете либо предоставить клиенту интерфейс Java, который вы используете на сервере, либо предоставить ему WSDL. В этом случае клиент отвечает за создание клиентского интерфейса из WSDL. В обоих случаях JaxWsProxyFactoryBean используется для создания прокси, реализующего этот интерфейс. - person Tomasz Nurkiewicz; 27.01.2012
comment
О, я вижу. А если я дам ему WSDL, как его использовать? Не могли бы вы дать фрагмент кода или ссылку на какую-нибудь статью? - person Dmitry; 27.01.2012
comment
@Dmitry: Конечно, здесь есть статья о wsdl2java с Apache CXF . Рабочий процесс прост — этот инструмент генерирует классы Java для всех элементов, объявленных с использованием схемы XML и интерфейса Java для каждой конечной точки. Клиентский код Apache CXF знает, что с ними делать. - person Tomasz Nurkiewicz; 27.01.2012

Вы можете использовать простую конфигурацию spring, подобную этой, для клиентской стороны -

<jaxws:client id="mywebServiceClient"
    serviceClass="com.saurzcode.TestService"
    address="http://saurzcode.com:8088/mockTestService">

    <jaxws:binding>
        <soap:soapBinding version="1.2" mtomEnabled="true" />
    </jaxws:binding>
</jaxws:client>
<cxf:bus>
    <cxf:outInterceptors>
        <bean class="com.saurzcode.ws.caller.SoapHeaderInterceptor" />
    </cxf:outInterceptors>
</cxf:bus>

Игнорируйте Interceptor, если он вам не нужен.

Подробнее читайте в этом сообщении.

person saurzcode    schedule 28.05.2014
comment
Как внедрить этого клиента в бин? - person Marcin Erbel; 20.01.2015
comment
@MarcinErbel Можете ли вы уточнить, что именно вы ищете? - person saurzcode; 22.01.2015
comment
Хорошо, у меня только что были проблемы в моем репозитории mvn. Я думал, что внедрить Client внутрь bean-компонента намного сложнее. Нвм, но спасибо за ответ. - person Marcin Erbel; 22.01.2015