Over a million developers have joined DZone.

Exploring a Top-Down SOAP Service: Part II

As we continue diving into SOAP services for Java apps, see what it takes for clean installs and to set up proper testing.

· Java Zone

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

Intro

When we left off last time, we had succeeded in getting a bare-bones WSDL definition to generate some code, using the Apache CXF cxf-codegen-plugin (Maven).

I added only the absolutely necessary pieces to the WSDL, one step a time, so that we could observe what errors were produced, and so we could learn what we might be missing. Hopefully, this might be a helpful reference if you ever encounter some error message.

We continue here by diving into the generated code, and improving our project structure and WSDL, and we'll try to actually deploy and run at each step.

Just a reminder from the last article — if you have a better way to do this, great! These articles are not intended to be comprehensive. This is just one way to do it. I tried to strike a balance between doing something at the cutting-edge of best practices or technology, with the practicalities of delivering a project, not over-engineering, trying avoid too much code-bloat, and not thinking I can foresee the future of a project (its direction and longevity).

I think the forte of these articles lie in working step-by-step and demonstrating possible errors by letting them occur.

Latest Code

You can get the latest code here.

and the base (or child) project here.

The Generated Source

Image title

The ShapeCalculatorWebServicePortImpl is where we will add our code to invoke our other project (the Shape Calculator from this series of articles), and the ShapeCalculatorWebService is the interface implemented.

Interface (ShapeCalculatorWebService)

@WebService(targetNamespace = "http://ws.service.shape.calc.eli.com/", name = "ShapeCalculatorWebService")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@Generated(value = "org.apache.cxf.tools.wsdlto.WSDLToJava", date = "2016-09-21T12:04:15.336-04:00", comments = "Apache CXF 3.1.7")
public interface ShapeCalculatorWebService {

    @WebMethod
    @Oneway
    @Generated(value = "org.apache.cxf.tools.wsdlto.WSDLToJava", date = "2016-09-21T12:04:15.336-04:00")
    public void runAllPendingRequestsNoStopOnError();
}

Implementation (ShapeCalculatorWebServiceImpl)

@javax.jws.WebService(
                      serviceName = "ShapeCalculatorWebService",
                      portName = "ShapeCalculatorWebServicePort",
                      targetNamespace = "http://ws.service.shape.calc.eli.com/",
                      wsdlLocation = "file:/C:/_dzone-article-sandbox/eclipse-workspace/ws-soap-top-down-p2/WebContent/wsdl/ShapeCalcWebService.wsdl",
                      endpointInterface = "com.eli.calc.shape.service.ws.ShapeCalculatorWebService")

@Generated(value = "org.apache.cxf.tools.wsdlto.WSDLToJava", date = "2016-09-21T12:04:15.091-04:00", comments = "Apache CXF 3.1.7")
public class ShapeCalculatorWebServicePortImpl implements ShapeCalculatorWebService {

    @Generated(value = "org.apache.cxf.tools.wsdlto.WSDLToJava", date = "2016-09-21T12:04:15.091-04:00")
    private static final Logger LOG = Logger.getLogger(ShapeCalculatorWebServicePortImpl.class.getName());

    /* (non-Javadoc)
     * @see com.eli.calc.shape.service.ws.ShapeCalculatorWebService#runAllPendingRequestsNoStopOnError()*
     */
    @Generated(value = "org.apache.cxf.tools.wsdlto.WSDLToJava", date = "2016-09-21T12:04:15.091-04:00")
    public void runAllPendingRequestsNoStopOnError() { 
        LOG.info("Executing operation runAllPendingRequestsNoStopOnError");
        try {
        } catch (java.lang.Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

}

Set Up Web Service Project

Let's see if we can get what we have so far to run.

For more details, you can check out the articles The Java Web App Journey... SOAP Services (parts 1 through 4). To obtain these changes, there is a link near the end of this article.

We need to add CXF's http-transport to the POM:

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>${cxf.version}</version>
</dependency>

And we will need the servlet api ....

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>


To help us get going quickly, let's add our classes from the previous bottom-up web service project:

Image title

Attempt a Build

Let's do a Maven install... and we get an error. It is because our config class, WebServiceContext, is expecting to initialize a ShapeCalculatorWebService.

We need to copy the interface and implementation over to src/main/java. I am going to do that because src/main/java is really where the working sources will reside. If we stay using the files in target/generated-sources, then every time we do another WSDL change, the new auto-generated files will overwrite our changes.

There may be a way to make this part of the process smarter (please comment) but to me at the moment, it's a sideshow; a distraction.

Image title

Again, there's probably a better way (I tried searching for ways to have the WSDL specify a different namespace for the interface vs the implementation), but I manually made this change:

Image title

The WebServiceContext class still complains, and the reason is that it expects the implemenation name to be ShapeCalculatorWebServiceImpl, but our generated class is ShapeCalculatorWebServicePortImpl.

We have a choice of modifying the WebServiceContext, or go back to our WSDL:

    <wsdl:service name="ShapeCalculatorWebService">
        <wsdl:port name="ShapeCalculatorWebServicePort" binding="tns:ShapeCalculatorWebServiceSoapBinding">
        </wsdl:port>
    </wsdl:service>

I went with changing the WSDL and removed Port off the end of <wsdl:port name="...... >.

Then I re-copied just the implementation to its proper destination in src/main/java. I also made a change to the logging, removing the auto-generated code and replacing it with the slf4j library.

Build Is Good

... And this time. we have a clean Maven install.

Start Database

We have been using MySQL... here is one of the previous articles detailing this section, so I won't go into it here.

Start Server

We start our Eclipse-managed Tomcat server, and watch the console... looks like a clean start, Spring and Hibernate did their thing.

Test URL

Let's see what happens if we point our browser to this new service:

Image title

Image title


Using SOAPUI, we create a new SOAP project with the WSDL URL.

Image title

....and we get this:

Image title

Hmm.... "no endpoint set".

Back to The WSDL

We are missing the following inside of the  <wsdl:service......>  section.

<soap:address location="http://localhost:8080/web-service-soap-bottom-up/services/ws/ShapeCalculatorWebService"/>


Install, Run, Test

This time, it works:

Image title

If we run the request, it is blank response, but the console output indicates we did invoke the operation:

    @Generated(value = "org.apache.cxf.tools.wsdlto.WSDLToJava", date = "2016-09-21T13:21:57.958-04:00")
    public void runAllPendingRequestsNoStopOnError() { 
        LOG.debug("\n\n\nExecuting operation runAllPendingRequestsNoStopOnError\n\n\n");
        try {
        } catch (java.lang.Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

There is a blank response in SOAPUI because the method is a void return.

Baseline

So, we now know we have a baseline that works, all the way from editing the WSDL, to generating the sources, to a build and install, and testing to get a response.

Coming Up Next...

Our test of our first operation works — however, it is lacking. There's no response indication, and that lack of response breaks from the requirements we were given.

Let's see how we might improve our current operation, in the next article.

Latest Code

You can get the latest code here.

Stay tuned for the next article!

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
soap ,wsdl ,maven ,java

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}