简体   繁体   中英

Java different parameter type needed for identical SOAP Web Service?

I have a Web Service client for 2 identical SOAP Web Services called Company1Service and Company2Service. Both these web services have the exact same PurchaseOrder class.

However, when I want to call the m1ProcessPurchaseOrder() method and the m2ProcessPurchaseOrder() method from each web service, they require different parameter types for the Po object. Yet, the PurchaseOrder class is identical for both services.

I am using NetBeans and the Generated Sources (jax-ws).

public boolean m1ProcessPurchaseOrder(ab.service.company1.PurchaseOrder Po) 
{
    ab.service.company1.Company1Service port = service1.getComapny1ServicePort();
    return port.processPurchaseOrder(po);
}

public boolean m2ProcessPurchaseOrder(ab.service.company2.PurchaseOrder Po) 
{
    ab.service.company2.Company2Service port = service2.getComapny2ServicePort();
    return port.processPurchaseOrder(po);
}

What I would like to do is have ab.service.company1.PurchaseOrder be the parameter type for both the Company1Service and the Company2Service.

Here is my error if I try to change m2ProcessPurchaseOrder() parameter type to ab.service.company1.PurchaseOrder :

method processPurchaseOrder in interface Company2Service cannot be applied to given types;

Required: ab.service.Company2.PurchaseOrder

Found: ab.service.Company1.PurchaseOrder

Reason: actual argument ab.service.Company1.PurchaseOrder cannot be converted to ab.service.Company2.PurchaseOrder by method invocation conversion

Depending on what JAX-WS implementation you are using -- there are severals: CXF , RI/Metro , Axis2 , JBossWS , Spring-WS , etc. -- you might be needing to invoke different tools to generate your artifacts ( XSD Schemas or WSDL 's), ie RI's wsimport , or a specific JAX-WS implementation tools like *Axis*2's or CXF 's WSDL2Java , or JBossWS ' wsprovide .

Also, depending on what build script/tool you have setup for your project, there might be a task, goal, or a target that you can utilize to automate the invocation of these tools. Nevertheless, when it comes to XML-to-Java binding, you can utilize JAXB Binding document(s) to manipulate the generated Java classes including the manipulation of where (package) they are generated into. This is done via jaxb:bindings ( jaxb is just a namespace prefix). For WSDL artifacts, ie service, you can place your mapping instructions in jaxws:bindings (same here jaxws is just an XML namespace). Note that these two are two separate binding ( XML ) documents which can be fed to one of the aforementioned tools, ie CXF 's WSDL2Java or wsimport .

For a JAXB binding, you can create a binding document like ( Company1Binding.xml ):

<?xml version="1.0" encoding="UTF-8" ?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1">

  <jaxb:bindings schemaLocation="PurchaseOrder.xsd">
    <jaxb:schemaBindings>
      <jaxb:package name="ab.service.common" />
    </jaxb:schemaBindings>
  </jaxb:bindings>

  <!-- more binding related to Company1Service -->

</jaxb:bindings>

and a JAXB binding for Company2Binding.xml :

<?xml version="1.0" encoding="UTF-8" ?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1">

  <jaxb:bindings schemaLocation="PurchaseOrder.xsd">
    <jaxb:schemaBindings>
      <jaxb:package name="ab.service.common" />
    </jaxb:schemaBindings>
  </jaxb:bindings>

  <!-- more binding related to Company2Service -->

</jaxb:bindings>

This would place a generated PurchaseOrder.java class in ab.service.common package, so you can reference the instances of this class in ab.service.company1.* and ab.service.company2.* from this single class ( ab.service.common.PurchaseOrder.java ).

Note that I place such binding in both Company1's and Company2's in case you make changes to PurchaseOrder.xsd at some point, and generate the binding only one of the services, ie Company1's. In this case, PurchaseOrder.java is regenerated for both, since there is only one generated class for it ( ab.service.common.PurchaseOrder.java ).

You can do the same with WSDL artifacts, for example for Comapny1Service.wsdl , you can create a new binding document like ( Company1ServiceBinding.xml ):

<?xml version="1.0" encoding="UTF-8"?>
<jaxws:bindings xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    version="2.1" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
    wsdlLocation="Company1Service.wsdl">

    <jaxws:bindings node="wsdl:definitions">
        <jaxws:package
            name="ab.service.company1" />
    </jaxws:bindings>

    <jaxws:bindings
        node="wsdl:definitions/wsdl:portType/wsdl:operation/wsdl:fault[@name='fault']">
        <jaxws:class
            name="ab.service.common.ServiceException" />
    </jaxws:bindings>

</jaxws:bindings>

Which would place the service classes (like the interface, client proxy, along side, say, Soap Fault type you specified in your WSDL for the operations) in ab.service.Company1 package. Notice the difference between the namespaces in each binding document ( jaxb:bindings vs. jaxws:bindings ). Finally, you can pass these binding information to the actual tool, ie CXF 's WSDL2Java (in this case, a snippet of code from Ant build file):

<java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true">
    <arg value="-d"/>
    <arg value="${path.to.generated.code}"/>
    <arg value="-b"/>
    <arg value="${path.to.artifacts}/Company1Binding.xml"/>
    <arg value="-b"/>
    <arg value="${path.to.artifacts}/Company1ServiceBinding.xml"/>
    <arg value="${path.to.artifacts}/Company1Service.wsdl"/>
    <classpath>
        <path refid="${jaxws.impl.library.path}"/>
    </classpath>
</java>

(NOTE: you should have a similar target for Company2Service )

As you can see, this particular tool accepts binding documents ( JAXB and JAX-WS ) via a -b flag. As a matter of fact, the Binding Compiler (xjc) which these tools, like WSDL2Java , ultimately call, do accept the binding documents via -b option (note the link takes you to Reference Implementation/Metor 's version of xjc , but CXF 's and others' should be close). As a matter of fact, you could have just call the WSDL2Java itself directly:

/path/to/wsdltojava -d /path/to/where/you/want/to/generate -b /path/to/wsdl/artifacts/CompanyBinding.xml -b /path/to/wsdl/artifacts/Company1ServiceBinding.xml /path/to/wsdl/artifacts/Company1Service.wsdl

Mapping using JAXB requires getting yourself familiarized with a bit of details, but you can read more about it here which is JAX-WS RI/Metro 's. For CXF 's, you can refer to here , and some examples for Maven's plugin for CXF 's WSDL2Java . Again, every JAX-WS implementation has its own set of tools, but the concepts are identical when it comes to the underlying mapping/binding which is tied to JAXB .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM