The WSDL-first JAX-WS sample is a simple Hello World application developed using the JAX-WS APIs. The sample demonstrates using a WSDL-first development approach to:
Run a simple client against a standalone server using SOAP 1.1 over HTTP
Configure FUSE Services Framework to enable schema validation on the client and/or server side
This sample includes a WSDL file that defines the operations and the data exchanged with the service. When you run this sample, the client and server applications send greetings back and forth. The client sends one of the messages with an invalid length string, which causes the server to throw an exception defined in the WSDL file.
When you enable schema validation, the server and client throw marshaling and
unmarshaling exceptions defined in a configuration file that you add to your
CLASSPATH
(see Enabling schema validation).
The hello_world.wsdl
file for this sample defines four operations
for the service:
Example 5.1. WSDL-First Sample: hello_world.wsdl
<wsdl:portType name="Greeter"> <wsdl:operation name="sayHi"> <wsdl:input message="tns:sayHiRequest" name="sayHiRequest"/> <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"/> </wsdl:operation> <wsdl:operation name="greetMe"> <wsdl:input message="tns:greetMeRequest" name="greetMeRequest"/> <wsdl:output message="tns:greetMeResponse" name="greetMeResponse"/> </wsdl:operation> <wsdl:operation name="greetMeOneWay"> <wsdl:input message="tns:greetMeOneWayRequest" name="greetMeOneWayRequest"/> </wsdl:operation> <wsdl:operation name="pingMe"> <wsdl:input name="pingMeRequest" message="tns:pingMeRequest"/> <wsdl:output name="pingMeResponse" message="tns:pingMeResponse"/> <wsdl:fault name="pingMeFault" message="tns:pingMeFault"/> </wsdl:operation> </wsdl:portType>
The client and server do the following when you run the sample:
The client invokes sayHi
and the server responds.
The client invokes greetMe
and the server responds.
The client invokes greetMe
with an invalid length string and expects
an error. The server executes pingMe
and throws a
PingMeFault
exception.
The client invokes greetMeOneWay
and expects no response from the
server.
These instructions use Maven to build and run the sample, using the pom.xml
file located the base directory of this sample. If you prefer to use wsdl2java, javac, and
java to build and run the sample, see the ReadMe file located in your
install_dir\samples\wsdl_first
directory.
See About Maven and Installing and setting up Maven for more information about using Maven with the FUSE Services Framework samples.
Initially, you will run the sample without using a configuration file. Later you will
add the file, cxf.xml
, to the CLASSPATH
to run the sample
with schema validation.
To build and run the sample:
Open a console to the sample directory,
install_dir\samples\wsdl_first
and enter the following
command to build the sample:
mvn install
Maven builds the sample and downloads required JAR files to your Maven repository:
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Building Unnamed - org.apache.cxf.samples:wsdl_first:jar:1.0 [INFO] task-segment: [install] [INFO] ------------------------------------------------------------------------ ... [INFO] Installing install_dir\samples\wsdl_first\target\wsdl_first-1.0.jar to ...\.m2\repository\org\apache\cxf\samples\wsdl_first\1.0\wsdl_first-1.0.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ ...
Enter the following command to start the server:
mvn -Pserver
When the server is started, the console displays the message Server
ready...
.
Open another console at the same location and enter the following command to start the client:
mvn -Pclient
The client starts and sends a greeting to the server. The client and server consoles show the messages sent back and forth as the sample runs.
The messages appear rapidly in the consoles as the sample runs. When the messages have all been sent, you can scroll up in the console windows to observe the following events:
The client invokes sayHi
, and receives a response from the
server:
Client Console
Invoking sayHi...
Server responded with: Bonjour
Messages in the server console indicate that the server executes the
sayHi
operation:
Server Console
Mar 23, 2009 9:45:57 AM demo.hw.server.GreeterImpl sayHi
INFO: Executing operation sayHi
Executing operation sayHi
The client (in this example, Bob
) then invokes greetMe
and receives a response from the server:
Client Console
Invoking greetMe...
Server responded with: Hello Bob
Messages in the server console indicate that the server executes the
greetMe
operation:
Server Console
... demo.hw.server.GreeterImpl greetMe
INFO: Executing operation greetMe
Executing operation greetMe
Message received: Bob
The client invokes greetMe
with an invalid length string and expects
an exception:
Client Console
Invoking greetMe
with invalid length string, expecting exception...
The server executes pingMe
and throws a PingMeFault
exception:
Server Console ...demo.hw.server.GreeterImpl greetMe INFO: Executing operation greetMe Executing operation greetMe Message received: Invoking greetMe with invalid length string, expecting exception... ...demo.hw.server.GreeterImpl pingMe INFO: Executing operation pingMe, throwing PingMeFault exception Executing operation pingMe, throwing PingMeFault exception
The client invokes greetMeOneWay
and gets no response because this is
a one-way operation:
Client Console
Invoking greetMeOneWay...
No response from server as method is OneWay
The client invokes pingMe
and expects an exception:
Client Console Invoking pingMe, expecting exception... Expected exception: PingMeFault has occurred: PingMeFault raised by server FaultDetail major:2 FaultDetail minor:1
The server throws an exception, executes greetMeOneWay
, and
exits:
Server Console ...org.apache.cxf.phase.PhaseInterceptorChain doIntercept INFO: Application has thrown exception, unwinding now: org.apache.hello_world_soap_http.PingMeFault: PingMeFault raised by server ...demo.hw.server.GreeterImpl greetMeOneWay INFO: Executing operation greetMeOneWay Executing operation greetMeOneWay Hello there Bob
To remove the code generated from the WSDL file and the *.class
files, run
mvn clean
.
By default, message parameters are not validated, but you can use a configuration file
to enable message parameter validation. This sample includes a configuration file,
cxf.xml
, that changes the default behavior to enable schema validation on
the client proxy and server endpoint:
A JAX-WS client proxy created for the port
{http://apache.org/hello_world_soap_http}SoapPort
will have schema
validation enabled.
The cxf.xml
configuration file includes the following bean to enable
schema validation on the client:
Example 5.2. Schema Validation on the Client
<jaxws:client name="{http://apache.org/hello_world_soap_http}SoapPort" createdFromAPI="true"> <jaxws:properties> <entry key="schema-validation-enabled" value="true" /> </jaxws:properties> </jaxws:client>
A JAX-WS server endpoint created for the port
{http://apache.org/hello_world_soap_http}SoapPort
will have schema
validation enabled.
The cxf.xml
configuration file includes the following bean to enable
schema validation on the server endpoint:
Example 5.3. Schema Validation on the Server Endpoint
<jaxws:endpoint name="{http://apache.org/hello_world_soap_http}SoapPort" wsdlLocation="wsdl/hello_world.wsdl" createdFromAPI="true"> <jaxws:properties> <entry key="schema-validation-enabled" value="true" /> </jaxws:properties> </jaxws:endpoint>
When you run this sample with the cxf.xml
configuration file added to the
CLASSPATH
, the client's second greetMe
invocation causes an
exception (a marshaling error) on the client side. This exception occurs before the request
with the invalid parameter is sent.
You can comment out the definition of the jaxws:client
element in the
cxf.xml
configuration file, then run the sample again to observe that the
client's second greetMe
invocation still throws an exception. This time the
exception is caused by an unmarshaling error on the server side.
You can comment out both elements, or remove the cxf.xml
file from your
CLASSPATH
, to restore the default behavior.
To run the sample with schema validation.
Add cxf.xml
to your CLASSPATH
environment
variable.
Start the server and client again. After the sample runs, scroll through the server and client consoles to observe the messages exchanged.
This time, when the client invokes greetMe
with an invalid length
string, the client catches an WebServiceException before the message is sent, and
generates a marshaling error:
Client Console Caught expected WebServiceException: Marshalling Error: cvc-maxLength-valid: Value 'Invoking greetMe with invalid length string, expecting exception...' with length = '67' is not facet-valid with respect to maxLength '30' for type 'MyStringType'.
Edit the configuration file to comment out the definition of the
<jaxws:client>
. When you run the sample this time, the
second greetMe
invocation throws an exception that is caused by an
unmarshaling error on the server side:
Server Console ...org.apache.cxf.phase.PhaseInterceptorChain doIntercept INFO: Interceptor has thrown exception, unwinding now org.apache.cxf.interceptor.Fault: Unmarshalling Error: cvc-maxLength-valid: Value 'Invoking greetMe with invalid length string, expecting exception...' with length = '67' is not facet-valid with respect to maxLength '30' for type 'MyStringType'. ... Caused by: javax.xml.bind.UnmarshalException - with linked exception: [org.xml.sax.SAXParseException: cvc-maxLength-valid: Value 'Invoking greetMe with invalid length string, expecting exception...' with length = '67' is not facet -valid with respect to maxLength '30' for type 'MyStringType'.]
Messages in the client console show the that the WebServiceException is caught and an unmarshalling error is generated:
Client Console Invoking greetMe with invalid length string, expecting exception... Caught expected WebServiceException: Unmarshalling Error: cvc-maxLength-valid: Value 'Invoking greetMe with invalid length string, expecting exception...' with length = '67' is not facet-valid with respect to maxLength '30' for type 'MyStringType'.
Edit the configuration file to comment out both the
<jaxws:client>
and
<jaxws:endpoint>
elements to restore the default
behavior. Alternatively, remove cxf.xml
from your
CLASSPATH
.
When you run the Maven mvn install
command, Maven compiles the Java files
and creates Java class files. Maven creates the
install_dir\samples\wsdl_first\target
directory, which includes the
client and server class files.
When you run the Maven mvn -Pserver
and mvn -Pclient
commands,
Maven starts the server and client and executes the operations in the WSDL and Java class
files.
The sample files in the wsdl_first
directory include the
following:
pom.xml
— This file is used by the Maven tooling
when creating the service unit and required files for packaging and deploying the
service into a container.
install_dir\samples\wsdl_first\wsdl\hello_world.wsdl
— Using the WSDL-first approach, the first step in designing services is to
define your services in WSDL and XML Schema before writing any code. Examine this
file to see how the service is defined, including the following:
The WSDL types for each of the elements used with the service, for example:
<wsdl:types>
...
<simpleType name="MyStringType">
<restriction base="string">
<maxLength value="30" />
</restriction>
</simpleType>
<element name="greetMe">
<complexType>
<sequence>
<element name="requestType"
type="tns:MyStringType"/>
</sequence>
</complexType>
</element>
...
The operations used with the service. Example 5.1 shows the
operations defined for the service, including the three greetings sent by the
client and the pingMe
that defines the PingMeFault
exception thrown for invalid length string greetings.
The WSDL binding and transport used by the service. This sample specifies a SOAP binding and a transport that corresponds to the HTTP binding in the SOAP specification:
... <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
Examine the WSDL file to see all the details of the service definition.
install_dir\samples\wsdl_first\cxf.xml
— This
configuration file enables schema validation when included on the
CLASSPATH
. See Enabling schema validation.
install_dir\samples\wsdl_first\src\demo\hw\client\*.java
— Java files that define the client classes. Examine
Client.java
to see how the client invokes the operations defined in
hello_world.wsdl
.
install_dir\samples\wsdl_first\src\demo\hw\server\*.java
— Java files that define the server classes.
OSGi is a mature, lightweight, component system that solves many challenges associated with medium and large scale development projects. Through the use of bundles complexity is reduced by separating concerns and ensuring dependencies are minimally coupled via well defined interface communication. This also promotes the reuse of components in much the same way that SOA promotes the reuse of services. And, since each bundle effectively is given an isolated environment, and since dependencies are explicitly defined, versioning and dynamic updates are possible. These are just a few of the many benefits of OSGi. Users wishing to learn more should check out http://www.osgi.org/Main/HomePage.
Before you can install an application into an OSGi container, you must package it into one or more OSGi bundles. An OSGi bundle is a JAR that contains extra information that is used by the OSGi container. This extra information specifies the packages this bundle exposes to the other bundles in the container and any packages on which this bundle depends.
See the chapter "Deploying to an OSGi Container" in Configuring and Deploying FUSE™ Services Framework Endpoints , for more information about deploying to an OSGi container, and for instructions that use this WSDL-first sample to demonstrate the steps of installing an application into an OSGi container.