Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apache CXF + Spring: Generating a Simple Client

I've started learning the Apache CXF with Spring. First of all, I've tried to create a simple client/server model.

The server-side is: 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;
   }
}

The client-side is: 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 =)

Thanks in advance.

like image 743
Dmitry Avatar asked Jan 27 '12 11:01

Dmitry


2 Answers

You can use a simple spring configuration like this for client side -

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

Ignore the Interceptor if you don't need it.

More details in this post.

like image 106
saurzcode Avatar answered Sep 22 '22 00:09

saurzcode


If you are doing code-first WS development then it is fine to distribute the interface and give it to the client. I believe @WebService is not needed (?) on the interface (only implementation), so the client does not have dependencies on this annotation.

Even if you are doing code-first web-services, you may still download the WSDL document generated for you by Apache CXF and give it to the client instead. With this approach (which is considered more mature, not to mention it can be used on different platforms like .NET) the client has to generate the stubs (using tool like wsdl2java). This process will essentially create very similar client interface automatically.

That's one of the reasons why so many people prefer contract-first development - the same WSDL is used to generate client-side stubs and server-side WS implementation. This limits the scope of (accidental) incompatibilites.

like image 31
Tomasz Nurkiewicz Avatar answered Sep 18 '22 00:09

Tomasz Nurkiewicz