You can expose a Service Component Architecture (SCA) application
as a web service by configuring an SCA web service binding.
About this task
The web service binding enables SCA applications to expose
services as web services to external clients and gives SCA components
access to external web services. External clients that access SCA
services exposed as web services might or might not be implemented
as an SCA component. You can use the web service binding element <binding.ws> within
either a component service or a component reference definition. When
this binding is used with a component service, the web service binding
enables clients to access a service that is offered by a particular
component as a web service. If the web service binding is used with
a component reference, components in an SCA composite can consume
an external web service and access it like any other SCA component.
The
product supports Web Services Description Language (WSDL) Version
1.1 definitions that also conform to the WS-I Basic Profile Version
1.1 and Simple SOAP Binding Profile 1.0 standards, and use the document
literal style. For OASIS-level applications only, the rpc-literal
style is also supported as long as it conforms to the above WS-I profiles.
All these conditions are required for support.
An SCA web service
binding is a WSDL-based binding; meaning that the binding either references
an existing WSDL document or enables you to specify enough information
to generate a WSDL document.
You can typically use the same
policy set functionality, that you use for defining qualities of service
on Java EE-based web services that are running in the application
server, to define quality of service definitions on SCA clients and
services that use the SCA web service binding. When the instructions
for administratively configuring these policy set definitions are
different for SCA-based web services than they are for Java EE-based
web services, then special topics and instructions are provided in
this information center. If there are no special instructions for
SCA, configure the corresponding quality of service on the SCA-based
web service the same way that you would configure that quality of
service for a Java EE-based web service.
Supported configurations: An
SCA web service binding provides support for providing and consuming
services using the SOAP Version 1.1 over HTTP and SOAP V1.2 over HTTP
protocols.
sptcfg
Supported configurations: The product does not support
the following functions:
- Java API for XML-Based Web
Services (JAX-WS) handlers when using a SCA web service binding
- Message Transmission Optimization Mechanism (MTOM) or SOAP with
Attachments (SwA) binary message optimizations
Use an SCA web service binding without implementing JAX-WS handlers.
Do not use SwA binary message optimizations or MTOM optimizations
for transferring binary data between SCA clients and services that
use the SCA web services binding. Instead of implementing MTOM or
SwA binary message optimizations to send binary data, use the base64Binary
XML Schema Definition (XSD) encoding to embed the data within the
SOAP message.
sptcfg
Procedure
- Configure an SCA service with an SCA web service binding.
Depending on whether you develop your SCA service using the
top-down approach starting with an existing WSDL file or you develop
your SCA service using the bottom-up approach starting with existing
Java code, you might or might not have a WSDL file available. Also,
the WSDL file might define only a portType or it might include a port
definition as well.
- For SCA applications that are developed top-down starting
from a WSDL port, you must refer to the port definition in the existing
WSDL file by adding a <binding.ws> element as
a child of your <service> element. An example
of the syntax for this step follows:
<binding.ws wsdlElement=<port target Namespace>#wsdl.port(<service name attr>/<port name attr>)/>
The
location attribute of the <address> element for
the port is ignored by the runtime environment when determining the
URL at which your service is invoked.
The following WSDL file
and composite definition illustrate this scenario:
WSDL file
<wsdl:definitions targetNamespace="http://www.ibm.com/" xmlns:tns="http://www.ibm.com/" >
.
<wsdl:portType name="MyPortType ">
.
<wsdl:binding name="MyBinding" type="tns:MyPortType">
.
<wsdl:service name="MyService">
<wsdl:port binding="tns:MyBinding" name="MyPort">
<wsdlsoap:address location=""/>
</wsdl:port>
</wsdl:service>
Composite definition
<composite>
<component name="MyComponent">
<implementation.java class="test.MyCompImpl"/>
<service name="GuessAndGreetWrapped">
<interface.wsdl interface="http://www.ibm.com/#wsdl.interface(MyPortType)" />
<binding.ws wsdlElement="http:// www.ibm.com/#wsdl.port(MyService/MyPort)" />
</service>
</component>
</composite>
- For SCA applications that are developed top-down starting
from a WSDL portType, you must create an empty <binding.ws> element
as the child of your <service> element. The empty <binding.ws> element
directs the runtime environment to generate a port that corresponds
to your WSDL portType definition. The generated port uses a SOAP 1.1
over HTTP WSDL binding.
The following WSDL file and composite definition
illustrate this scenario:
WSDL file
<wsdl:definitions targetNamespace="http://www.ibm.com/" xmlns:tns="http://www.ibm.com/" >
.
<wsdl:portType name="MyPortType ">
Composite definition
<composite>
<component name="MyComponent">
<implementation.java class="test.MyCompImpl"/>
<service name="GuessAndGreetWrapped">
<interface.wsdl interface="http://www.ibm.com/#wsdl.interface(MyPortType)" />
<binding.ws/>
</service>
</component>
</composite>
- For SCA applications that are developed bottom-up starting
from existing Java code, you must create an empty <binding.ws> element
as the child of your <service> element. The empty <binding.ws> element
directs the runtime environment to generate a WSDL portType that corresponds
to your Java interface, and a port with a SOAP 1.1 over HTTP WSDL
binding.
The following example demonstrates the <binding.ws> element
for this scenario:
<composite>
<component name="MyComponent">
<implementation.java class="test.MyCompImpl"/>
<service name="GuessAndGreetWrapped">
<binding.ws/>
</service>
</component>
</composite>
- Determine the endpoint URL and test the endpoint of your
deployed SCA service.
After you configure the SCA service
with a web service binding, you can test the endpoint for your deployed
SCA service. Accessing the endpoint with a web browser displays the
Axis2 cover page.
The endpoint URL is determined
based on one of the following scenarios:
- If there is no uri attribute on the binding,
the component resembles:
<component name="C1">
<service name="S1">
<binding.ws/>
Then the endpoint is:
http://<host>:<port>/C1_name/S1_name
- If the uri attribute on the binding is relative,
the component resembles:
<component name="C1">
<service name="S1">
<inding.ws name="B1" uri="U1"/>
Then the endpoint
is:
http://<host>:<port>/C1/U1
- If the uri attribute on the binding is absolute,
which applies to OASIS only and not to OSOA, the component resembles:
<component name="C1">
<service name="S1">
<inding.ws name="B1" uri="/U1"/>
Then the endpoint
is:
http://<host>:<port>/U1
For SCA services that are configured using wsdlElement#wsdl.service,
the ports are appended; for example:
http://<host>:<port>/Component_name/Service_name/Port_name
For
OASIS, wsdl.service is not supported.
- View WSDL or XSD documents for the SCA service with the
web service binding.
Append the query string ?wsdl to
the endpoint URL. Accessing the URL with a web browser returns the
outermost WSDL. You can then view included and imported documents
using relative URLs. However, the web container will not serve resources
under the WEB-INF or META-INF directories, so avoid putting WSDL documents
under these directories within the SCA asset if you want them to be
accessible using ?wsdl.
- Configure an SCA reference (client) with an SCA web service
binding.
- Configure the reference with an <interface.wsdl> element
that refers to the portType of the target service. Read
about developing SCA service clients to learn how to configure the
reference with an <interface.wsdl>.
- Resolve
the SCA reference to an actual endpoint of a deployed web
service using one of the mechanisms provided by the SCA web service
binding support.
- When the target web service is deployed as an SCA component service
in the same domain as the client component, you can resolve the reference
to the target component using the @target attribute of the <reference> element
for OSOA composites or the <binding.ws> element
for OASIS composites. Using the @target attribute eliminates
the need to know the specific URL of the deployed target service.
For
example, assume the target service is defined as follows:
<component name="TargetComponent">
<implementation.java />
<service name="MyService">
<interface.wsdl />
<binding.ws />
</service>
</component>
A reference in an OSOA composite can
be wired to this service as follows:
<component name="ClientComponent">
<implementation.java />
<!-- Resolution uses @target attribute on reference element. -->
<reference name="myRef" target=TargetComponent/MyService>
<interface.wsdl />
<!-- The binding does not need endpoint-related info added. -->
<binding.ws/>
</reference>
</component>
A reference in an OASIS composite
can be wired to this service as follows:
<component name="ClientComponent">
<implementation.java />
<reference name="myRef">
<interface.wsdl />
<!-- Resolution done using the @target attribute on binding element. -->
<binding.ws target=TargetComponent/MyService/>
</reference>
</component>
In these examples, the
binding.ws element
does not specify a wsdlElement attribute. The SCA run time creates
a SOAP binding, WSDL service, and WSDL port on each side. If your
service binding specifies a SOAP binding, either directly or indirectly
using the WSDL port, your reference binding must specify a compatible
SOAP binding.
If the target web service is not an SCA service in the same
domain as the client, you must use a binding-specific endpoint resolution
mechanism. You can also resolve a reference to an SCA service in the
same domain by using the binding-specific mechanisms, instead of using
the @target annotation.
- You can define the endpoint for a deployed web service in an existing
WSDL file using <wsdlsoap:address>. For example:
<wsdl:definitions targetNamespace=http://my.work/test/
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" >
...
<wsdl:portType name="MyPortType">
...
<wsdl:binding name="MyBinding" type="tns:MyPortType">
...
<wsdl:service name="MyService">
<wsdl:port name="MyPort" binding="tns:MyBinding">
<wsdlsoap:address
location="http://www.mywork.com:9080/TargetComponent/MyService "/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
The client points to the WSDL
port using a @wsdlElement attribute on the <binding.ws> element
using the following syntax:
<port target Namespace>#wsdl.port(service_name_attribute/port_name_attribute)"/>
For
example:
<component name="ClientComponent">
<implementation.java />
<reference name="myRef">
<interface.wsdl />
<binding.ws wsdlElement="http://my.work/test/#wsdl.port(MyService/MyPort)/>
</reference>
</component>
- If the endpoint is not present in the WSDL for the service, there
are several ways to specify the endpoint using the reference. In the
following WSDL file, the endpoint (wsdlsoap:address)
is not specified.
<wsdl:definitions targetNamespace=http://my.work/test/
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" >
...
<wsdl:portType name="MyPortType">
...
<wsdl:binding name="MyBinding" type="tns:MyPortType">
...
<wsdl:service name="MyService">
<wsdl:port name="MyPort" binding="tns:MyBinding">
...
<!-- In this case, the endpoint is not specified. -->
<wsdlsoap:address location=""/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
For OSOA, you can add the endpoint
to the composite definition. Add the @uri attribute to the <binding.ws> element
to specify the endpoint. For example:
<!-- An OSOA example composite definition. -->
<component name="ClientComponent">
<implementation.java />
<reference name="myRef">
<interface.wsdl />
<binding.ws wsdlElement="http://my.work/test/#wsdl.port(MyService/MyPort)
uri=http://www.mywork.com:9080/TargetComponent/MyService />
</reference>
</component>
For OASIS based references, one approach
is to add a WSDL binding to the reference. Then add @uri to the component <binding.ws> element.
<!-- An OASIS example composite definition. -->
<component name="ClientComponent">
<implementation.java />
<reference name="myRef">
<interface.wsdl interface="http://my.work/test/#wsdl.interface(MyPortType)"/>
<binding.ws uri=http://www.mywork.com:9080/TargetComponent/MyService
wsdlElement="http://my.work/test/#wsdl.binding(MyBinding) />
</reference>
</component>
- Optional: If your service or reference interface
is bidirectional such that a callback is defined, you must also configure
the web service binding on the callback.
- Configure callback for your SCA web services binding using
the WSDL port.
Configuring callback for your SCA web services binding
is similar to configuring an SCA service with the SCA web services
binding; however, you add a second service, the callback. When you
configure an SCA service with the SCA web services binding, you define
a WSDL port, either explicitly by pointing directly to a WSDL port
definition, or implicitly by giving the runtime enough information
to calculate a WSDL port. Similarly, you must also define a WSDL
port for the callback. A difference for the callback is that the runtime
environment defines the WSDL port that is used for the callback because
the runtime environment must keep this port tightly coupled to the
forward call. Therefore, the most you can do when developing your
SCA application using the top-down approach and defining a callback
for this service, is to point to a WSDL binding. For example:
<!-- Configuring a service with callback with web service binding -->
<component name="HelloWorldServiceComponent">
<implementation.java class="" />
<service name="HelloWorldService">
<interface.wsdl interface=http://www.ibm.com/sca/#wsdl.interface(HelloWorld)
callbackInterface= http://www.ibm.com/sca/#wsdl.interface(HelloWorldCallback)/>
<binding.ws wsdlElement="http://www.ibm.com/sca/#wsdl.port(HelloWorldService/HelloWorldSoapPort)"/>
<callback>
<binding.ws wsdlElement="http://www.ibm.com/sca/#wsdl.binding(HelloWorldCallbackSoapBinding)"/>
</callback>
</service>
</component>
The following example shows a
configuration of a client component with reference to this service
with callback defined. The reference and service configuration each
share the same view of which direction is the forward direction and
which is the callback direction.
<!-- Configuring a reference with callback with web service binding. -->
<component name="HelloWorldClientComponent">
<implementation.java class="" />
<reference name="helloWorldRef">
<interface.wsdl interface=http://www.ibm.com/sca/#wsdl.interface(HelloWorld)
callbackInterface= http://www.ibm.com/sca/#wsdl.interface(HelloWorldCallback)/>
<binding.ws wsdlElement="http://www.ibm.com/sca/#wsdl.port(HelloWorldService/HelloWorldSoapPort)"/>
<callback>
<binding.ws wsdlElement="http://www.ibm.com/sca/#wsdl.binding(HelloWorldCallbackSoapBinding)" />
</callback>
</reference>
</component>
- Configure callback for your SCA web service binding using
the WSDL portType.
Similar to the scenario of configuring a service
with a web service binding when starting with a WSDL port, you also
configure an empty
<binding.ws> element to configure
callback using the WSDL portType. The following composite definition
example illustrates the scenario when starting with two WSDL portType
definitions that has such that one interface uses a forward direction
and the other interface uses callback:
<!-- Configuring a service with callback with web service binding -->
<component name="HelloWorldServiceComponent">
<implementation.java class="" />
<service name="HelloWorldService">
<interface.wsdl interface=http://www.ibm.com/sca/#wsdl.interface(HelloWorld)
callbackInterface= http://www.ibm.com/sca/#wsdl.interface(HelloWorldCallback)/>
<binding.ws/>
<callback>
<binding.ws/>
</callback>
</service>
</component>
<!-- Configuring a reference with callback with web service binding -->
<component name="HelloWorldClientComponent">
<implementation.java class="" />
<reference name="helloWorldRef">
<interface.wsdl interface=http://www.ibm.com/sca/#wsdl.interface(HelloWorld)
callbackInterface= http://www.ibm.com/sca/#wsdl.interface(HelloWorldCallback)/>
<binding.ws/>
<callback>
<binding.ws/>
</callback>
</reference>
</component>
- Configure callback for your SCA web service binding using
the Java interface.
For the bottom-up case starting with a Java
interface, the composite definition is identical to the WSDL port
and portType scenarios, except that you must replace the
<interface.wsdl> elements
with the
<interface.java> element. For example:
<interface.java interface="helloworld.HelloWorldService"
callbackInterface="helloworld.HelloWorldCallback"/>
- (Optional: OASIS only) Configure your service to use SOAP
1.1 or 1.2.
You can configure your SCA web service to require a
particular SOAP version by providing an intent. For example:
<binding.ws requires="sca:SOAP.v1_2"/>
Supported
intents are sca:SOAP.v1_1 and sca:SOAP.v1_2.
Results
You have a configured SCA web service binding service or
reference.
There are additional ways for the web service binding
to generate a WSDL port that are not described in this topic. These
additional methods rely on WSDL generation at run time. This can cause
problems if the generated WSDL does not match the original WSDL obtained
from a service provider.
You can avoid problems by ensuring
that client package references the original WSDL obtained from a web
service provider. If you use the shortcut of omitting a client-side
reference to the WSDL, be sure to do so only in the case when you
are sure the WSDL port that is generated for the client is identical
to the WSDL port of the deployed service because the service port
is generated using the same algorithm.
For an example that is
not problematic, suppose you write a service using the bottom-up style,
starting from a Java interface, and deploy the service with a <binding.ws> element
with no attributes. This directs the runtime environment to generate
the WSDL port for this service. Also suppose an SCA client is developed
with access to the original Java classes used to write the service
implementation. This SCA client is used to test the SCA service using
a client-side reference with web service binding. You can configure
this reference without any knowledge of the service WSDL. In this
case, the reference interface is the original Java interface of the
service, and you can resolve the reference using the <reference> @target
mechanism. See the resolving SCA references documentation for more
information about using the @target attribute to resolve an SCA reference.
Using this approach, there is no WSDL to obtain or refer to in constructing
the client. This works because the product runtime environment maps
the service-side Java to WSDL in an identical manner as it maps the
client-side Java to WSDL.
In contrast, the following scenario
is problematic. Suppose that you write an SCA client with a web service
binding reference to a web service that is hosted on a platform other
than the product. It might seem reasonable to generate your Java client
from the service provider, and then ignore the WSDL from that point
on, avoiding the additional syntax in your client-side composite definition.
To do this, you use the <binding.ws> element
@uri attribute to specify the endpoint URL where the service is hosted.
This scenario is problematic because it forces the runtime environment
to generate a WSDL port for the client which might result in subtle
mismatches between the WSDL generated for the client side and the
actual WSDL port description of the deployed web service.
What to do next
Deploy your composite that has the SCA web services binding
service or reference.
Avoid trouble: If the composite
uses a bidirectional interface as an SCA service interface and a NullPointerException
results when you add your SCA module or application to a business-level
application (for example, using the wsadmin AdminTask.addCompUnit
command), you might need to add the SCA @Callback annotation to the
forward Java interface.
gotcha
A NullPointerException can occur
whether you are using a top-down development style (starting from
WSDL or XSD) or a bottom-up style (starting from Java). With the top-down
style, a composite definition typically includes a bidirectional interface
definition such as the following:
<interface.wsdl interface="http://forward.my/intf#wsdl.interface(ForwardIntf)"
callbackInterface="http://callback.my/intf#wsdl.interface(CallbackIntf)"/>
With
the bottom-up style, a composite definition typically includes a bidirectional
interface definition such as the following:
<interface.java interface="my.forward.intf.ForwardIntf"
callbackInterface="my.callback.intf.CallbackIntf"/>
The
NullPointerException can occur if the forward Java interface is not
annotated with @Callback, or more specifically @org.osoa.sca.annotations.Callback.
In the top-down example, the forward Java interface is the class generated
from portType, http://forward.my/intf/ForwardIntf using
the wsimport tool or my.forward.intf.ForwardIntf if
the default options are used. In the bottom-up example, the forward
Java interface is the class my.forward.intf.ForwardIntf.
To
fix the NullPointerException problem, add the @Callback annotation
to the forward Java interface and recompile. The @Callback annotation
is a class-level annotation with a single argument, the callback interface
Class object; for example:
...
import org.osoa.sca.annotations.Callback
@Callback(my.callback.intf.CallbackIntf.class)
public interface ForwardIntf {
...
If you are using the recommended top-down development
style, the forward Java interface is a generated class. It is generated
from the WSDL portType using the wsimport tool. Use the -s or -keep option
so that wsimport generates the Java source files, and then add the
@Callback annotation manually to the generated class and recompile.