8 Developing Web Service Clients
- Overview of WebLogic Web Services Client Development
- Invoking a Web Service from a Java SE Client
- Invoking a Web Service from a Standalone Java SE Client
- Invoking a Web Service from Another WebLogic Web Service
- Configuring Web Service Clients
- Defining a Web Service Reference Using the @WebServiceRef Annotation
- Managing Client Identity
- Using a Proxy Server When Invoking a Web Service
- Client Considerations When Redeploying a Web Service
- Client Considerations When Web Service and Client Are Deployed to the Same Managed Server
Parent topic: Developing Basic JAX-WS Web Service Clients
Overview of WebLogic Web Services Client Development
Invoking a web service refers to the actions that a client application performs to use the web service.
There are two types of client applications:
-
Java SE client—In its simplest form, a Java SE client is a Java program that has the
Main
public class that you invoke with thejava
command. A Java SE client can be invoked within a WebLogic Server environment (with access to the WebLogic Server classpath) or as a standalone client application. -
Jakarta EE component deployed to WebLogic Server—In this type of client application, the web service runs inside a Java Platform, Enterprise Edition (Jakarta EE) component deployed to WebLogic Server, such as an EJB, servlet, or another web service. This type of client application, therefore, runs inside a WebLogic Server container.
The sections that follow describe how to use Oracle's implementation of the JAX-WS specification to invoke a web service from a Java client application. You can use this implementation to invoke web services running on any application server, both WebLogic and non-WebLogic.
WebLogic Server optionally includes examples of creating and invoking WebLogic web services in the ORACLE_HOME
/wlserver/samples/server/examples/src/examples
directory, where ORACLE_HOME
represents the directory in which you installed WebLogic Server. For detailed instructions on how to build and run the examples, open the ORACLE_HOME
/wlserver/samples/server/docs/index.html
Web page in your browser and expand the WebLogic Server Examples->Examples->API->Web Services node. For more information, see Sample Applications and Code Examples in Understanding Oracle WebLogic Server.
For more information about:
-
Invoking message-secured web services, see Updating a Client Application to Invoke a Message-Secured Web Service in Securing WebLogic Web Services for Oracle WebLogic Server.
-
Best practices for developing web service clients, see Roadmap for Developing JAX-WS Web Service Clients.
-
Invoking web services asynchronously, see Developing Asynchronous Clients.
-
Creating a dynamic proxy client, using the
javax.xml.ws.Service
API, that enables a web service client to invoke a web service based on a service endpoint interface (SEI) dynamically at run-time (without usingclientgen
), see Developing Dynamic Proxy Clients. This chapter focuses on how to generate a static Java class of theService
interface implementation for the particular web service you want to invoke.
Parent topic: Developing Web Service Clients
Invoking a Web Service from a Java SE Client
The following table summarizes the main steps to create a Java SE application that invokes a web service.
Note:
In this section, it is assumed that:
-
When you invoke a web service using the client-side artifacts generated by the
clientgen
orwsdlc
Ant tasks, you have the entire set of WebLogic Server classes in your CLASSPATH. Support for standalone Java applications that are running in an environment where WebLogic Server libraries is described in Invoking a Web Service from a Standalone Java SE Client. -
You use Ant in your development environment to build your client application, compile Java files, and so on, and that you have an existing
build.xml
file that you want to update with web services client tasks. For general information about using Ant in your development environment, see Creating the Basic Ant build.xml File. For a full example of abuild.xml
file used in this section, see Sample Ant Build File for a Java Client.
Table 8-1 Steps to Invoke a Web Service from a Java SE Client
# | Step | Description |
---|---|---|
1 |
Set up the environment. |
Open a command window and execute the |
2 |
Update your |
See Using the clientgen Ant Task To Generate Client Artifacts. |
3 |
Get information about the web service, such as the signature of its operations and the name of the ports. |
|
4 |
Write the client application Java code that includes code for invoking the web service operation. |
See Writing the Java Client Application Code to Invoke a Web Service. |
5 |
Create a basic Ant build file, |
|
6 |
Compile and run your Java client application. |
- Using the clientgen Ant Task To Generate Client Artifacts
- Getting Information About a Web Service
- Writing the Java Client Application Code to Invoke a Web Service
- Compiling and Running the Client Application
- Sample Ant Build File for a Java Client
Parent topic: Developing Web Service Clients
Using the clientgen Ant Task To Generate Client Artifacts
The clientgen
WebLogic web services Ant task generates, from an existing WSDL file, the client artifacts that client applications use to invoke both WebLogic and non-WebLogic web services. These artifacts include:
-
The Java class for the
Service
interface implementation for the particular web service you want to invoke. -
JAXB data binding artifacts.
-
The Java class for any user-defined XML Schema data types included in the WSDL file.
For additional information about the clientgen
Ant task, such as all the available attributes, see Ant Task Reference in the WebLogic Web Services Reference for Oracle WebLogic Server.
Update your build.xml
file, adding a call to the clientgen
Ant task, as shown in the following example:
<taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask" /> <target name="build-client"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL" destDir="clientclasses" packageName="examples.webservices.simple_client" type="JAXWS"/> </target>
Before you can execute the clientgen
WebLogic web service Ant task, you must specify its full Java classname using the standard taskdef
Ant task.
You must include the wsdl
and destDir
attributes of the clientgen
Ant task to specify the WSDL file from which you want to create client-side artifacts and the directory into which these artifacts should be generated. The packageName
attribute is optional; if you do not specify it, the clientgen
task uses a package name based on the targetNamespace
of the WSDL. The type
is required in this example.
In this example, the package name is set to the same package name as the client application, examples.webservices.simple_client
. If you set the package name to one that is different from the client application, you would need to import the appropriate class files. For example, if you defined the package name as examples.webservices.complex
, you would need to import the following class files in the client application:
import examples.webservices.complex.BasicStruct; import examples.webservices.complex.ComplexPortType; import examples.webservices.complex.ComplexService;
Note:
The clientgen
Ant task also provides the destFile
attribute if you want the Ant task to automatically compile the generated Java code and package all artifacts into a JAR file. For details and an example, see "clientgen" in the WebLogic Web Services Reference for Oracle WebLogic Server.
If the WSDL file specifies that user-defined data types are used as input parameters or return values of web service operations, clientgen
automatically generates a JavaBean class that is the Java representation of the XML Schema data type defined in the WSDL. The JavaBean classes are generated into the destDir
directory.
For a full sample build.xml
file that contains additional targets from those described in this procedure, such as clean
, see Sample Ant Build File for a Java Client.
To execute the clientgen
Ant task, along with the other supporting Ant tasks, specify the build-client
target at the command line:
prompt> ant build-client
See the clientclasses
directory to view the files and artifacts generated by the clientgen
Ant task.
Parent topic: Invoking a Web Service from a Java SE Client
Getting Information About a Web Service
You need to know the name of the web service and the signature of its operations before you write your Java client application code to invoke an operation. There are a variety of ways to find this information.
The best way to get this information is to use the clientgen
Ant task to generate the web service-specific Service
files and look at the generated *.java
files. These files are generated into the directory specified by the destDir
attribute, with subdirectories corresponding to either the value of the packageName
attribute, or, if this attribute is not specified, to a package based on the targetNamespace
of the WSDL.
-
The
ServiceName
.java
source file contains thegetPortName()
methods for getting the web service port, whereServiceName
refers to the name of the web service andPortName
refers to the name of the port. If the web service was implemented with a JWS file, the name of the web service is the value of theserviceName
attribute of the@WebService
JWS annotation and the name of the port is the value of theportName
attribute of the<WLHttpTransport>
child element of the<jws>
element of thejwsc
Ant task. -
The
PortType.
java
file contains the method signatures that correspond to the public operations of the web service, wherePortType
refers to the port type of the web service. If the web service was implemented with a JWS file, the port type is the value of thename
attribute of the@WebService
JWS annotation.
You can also examine the actual WSDL of the web service; see Browsing to the WSDL of the Web Service for details about the WSDL of a deployed WebLogic web service. The name of the web service is contained in the <service>
element, as shown in the following excerpt of the TraderService
WSDL:
<service name="TraderService"> <port name="TraderServicePort" binding="tns:TraderServiceSoapBinding"> ... </port> </service>
The operations defined for this web service are listed under the corresponding <binding>
element. For example, the following WSDL excerpt shows that the TraderService
web service has two operations, buy
and sell
(for clarity, only relevant parts of the WSDL are shown):
<binding name="TraderServiceSoapBinding" ...> ... <operation name="sell"> ... </operation> <operation name="buy"> </operation> </binding>
Parent topic: Invoking a Web Service from a Java SE Client
Writing the Java Client Application Code to Invoke a Web Service
In the following code example, a Java application invokes a web service operation. The application uses standard JAX-WS API code and the web service-specific implementation of the Service
interface, generated by clientgen
, to invoke an operation of the web service.
The example also shows how to invoke an operation that has a user-defined data type (examples.webservices.simple_client.BasicStruct
) as an input parameter and return value. The clientgen
Ant task automatically generates the Java code for this user-defined data type.
Because the <clientgen>
packageName
attribute was set to the same package name as the client application, we are not required to import the <clientgen>
-generated files.
package examples.webservices.simple_client; /** * This is a simple Java application that invokes the * the echoComplexType operation of the ComplexService web service. */ public class Main { public static void main(String[] args) { ComplexService test = new ComplexService(); ComplexPortType port = test.getComplexPortTypePort(); BasicStruct in = new BasicStruct(); in.setIntValue(999); in.setStringValue("Hello Struct"); BasicStruct result = port.echoComplexType(in); System.out.println("echoComplexType called. Result: " + result.getIntValue() + ", " + result.getStringValue()); } }
In the preceding example:
-
The following code shows how to create a
ComplexPortType
stub:ComplexService test = new ComplexService(), ComplexPortType port = test.getComplexPortTypePort();
The
ComplexService
class implements the JAX-WSService
interface. ThegetComplexServicePortTypePort()
method is used to return an instance of theComplexPortType
stub implementation.
-
The following code shows how to invoke the
echoComplexType
operation of theComplexService
web service:BasicStruct result = port.echoComplexType(in);
The
echoComplexType
operation returns the user-defined data type calledBasicStruct
.
Parent topic: Invoking a Web Service from a Java SE Client
Compiling and Running the Client Application
Add javac
tasks to the build-client
target in the build.xml
file to compile all the Java files (both of your client application and those generated by clientgen
) into class files, as shown by the bold text in the following example:
<target name="build-client"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL" destDir="clientclasses" packageName="examples.webservices.simple_client" type="JAXWS"/> <javac srcdir="clientclasses" destdir="clientclasses" includes="**/*.java"/> <javac srcdir="src" destdir="clientclasses" includes="examples/webservices/simple_client/*.java"/> </target>
In the example, the first javac
task compiles the Java files in the clientclasses
directory that were generated by clientgen,
and the second javac
task compiles the Java files in the examples/webservices/simple_client
subdirectory of the current directory; where it is assumed your Java client application source is located.
In the preceding example, the clientgen
-generated Java source files and the resulting compiled classes end up in the same directory (clientclasses
). Although this might be adequate for prototyping, it is often a best practice to keep source code (even generated code) in a different directory from the compiled classes. To do this, set the destdir
for both javac
tasks to a directory different from the srcdir
directory. To run the client application, add a run
target to the build.xml
that includes a call to the java
task, as shown below:
<path id="client.class.path"> <pathelement path="clientclasses"/> <pathelement path="${java.class.path}"/> </path> <target name="run" > <java fork="true" classname="examples.webServices.simple_client.Main" failonerror="true" > <classpath refid="client.class.path"/> </target>
The path
task adds the clientclasses
directory to the CLASSPATH. The run
target invokes the Main
application, passing it the URL of the deployed web service as its single argument.
See Sample Ant Build File for a Java Client for a full sample build.xml
file that contains additional targets from those described in this procedure, such as clean
.
Rerun the build-client
target to regenerate the artifacts and recompile into classes, then execute the run
target to invoke the echoStruct
operation:
prompt> ant build-client run
You can use the build-client
and run
targets in the build.xml
file to iteratively update, rebuild, and run the Java client application as part of your development process.
Parent topic: Invoking a Web Service from a Java SE Client
Sample Ant Build File for a Java Client
The following example shows a complete build.xml
file for generating and compiling a Java client. See Using the clientgen Ant Task To Generate Client Artifacts and Compiling and Running the Client Application for explanations of the sections in bold.
<project name="webservices-simple_client" default="all"> <!-- set global properties for this build --> <property name="wls.hostname" value="localhost" /> <property name="wls.port" value="7001" /> <property name="example-output" value="output" /> <property name="clientclass-dir" value="${example-output}/clientclass" /> <path id="client.class.path"> <pathelement path="${clientclass-dir}"/> <pathelement path="${java.class.path}"/> </path> <taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask" /> <target name="clean" > <delete dir="${clientclass-dir}"/> </target> <target name="all" depends="clean,build-client,run" /> <target name="build-client"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL" destDir="${clientclass-dir}" packageName="examples.webservices.simple_client" type="JAXWS"/> <javac srcdir="${clientclass-dir}" destdir="${clientclass-dir}" includes="**/*.java"/> <javac srcdir="src" destdir="${clientclass-dir}" includes="examples/webservices/simple_client/*.java"/> </target> <target name="run" > <java fork="true" classname="examples.webservices.simple_client.Main" failonerror="true" > <classpath refid="client.class.path"/> </java> </target> </project>
Parent topic: Invoking a Web Service from a Java SE Client
Invoking a Web Service from a Standalone Java SE Client
In Invoking a Web Service from a Java SE Client, it is assumed that when you invoke a Web Service using the client-side artifacts generated by the clientgen
or wsdlc
Ant tasks, you have the entire set of WebLogic Server classes in your classpath. If, however, you do not have WebLogic Server installed locally, you can still invoke a Web Service by using one of the standalone WebLogic web services client JAR files.
Table 8-2 summarizes the standalone web service client JAR files that are available in the installation.
Table 8-2 Standalone Web Service Client JAR Files
JAR File | Location | Description |
---|---|---|
|
|
Supports basic JAX-WS client-side functionality including:
The standalone client JAR does not support invoking web services that use the following advanced features:
Note: For Web Services clients that have been developed with Jakarta EE APIs using the jakarta.* namespace, use thecom.oracle.webservices.wls.jaxws-wlswss-client.jakarta.jar
client jar file. Examples of such clients would be clients developed
with Helidon 3.0, Spring Framework 6.0, Spring Boot 3.0 or later
versions of these frameworks.
|
|
|
Supports the same functionality as
|
|
|
Supports the same functionality as
|
|
|
Provides support for WS-Secure Conversation security, as described in Configuring Secure Conversation in Securing Web Services and Managing Policies with Oracle Web Services Manager. |
To use a standalone web services client JAR file with your client application, perform the following steps:
-
Create a Java SE client using your favorite IDE, such as Oracle JDeveloper. For more information, see Developing and Securing Web Services and Clients in Developing Applications with Oracle JDeveloper.
-
Copy the required JAR files, defined in Table 8-2, from the computer hosting WebLogic Server to the appropriate directory on the standalone client computer.
For example, you might copy the files into the directory that contains other classes used by your client application.
-
Add the JAR files to your CLASSPATH.
Note:
Ensure that your CLASSPATH includes the JAR file that contains the Ant classes (
ant.jar
) as a subset are used by the standalone client JAR files. This JAR file is typically located in thelib
directory of the Ant distribution. -
Configure your environment for Oracle Web Services Manager (OWSM) policies. This step is optional, required only if you are attaching OWSM security policies to the web service client.
The configuration steps required vary based on the type of policy being attached. Examples are provided below.
For additional configuration requirements, see Configuring Java SE Applications to Use OPSS in Securing Applications with Oracle Platform Security Services.
Example: Basic Authentication
For example, to support basic authentication, using the
oracle/wss_http_token_client_policy
security policy, perform the following steps:-
Copy the
jps-config-jse.xml
andaudit-store.xml
files from thedomain_home
/config/fmwconfig
directory, wheredomain_home
is the name and location of the domain, to a location that is accessible to the web service client. -
Create a wallet (
cwallet.sso
) in the same location that you copied the files in step 2 that defines a map calledoracle.wsm.security
and the credential key name that the client application will use (for example,weblogic-csf-key
).The location of the file
cwallet.sso
is specified in the configuration filejps-config-jse.xml
with the element<serviceInstance>
.For more information, see Using a Wallet-based Credential Store in Securing Applications with Oracle Platform Security Services. -
On the Java command line, pass the following property defining the JPS configuration file copied in step 1:
-Doracle.security.jps.config=<pathToConfigFile>
For more information, see Scenario 3: Securing a Java SE Application in Securing Applications with Oracle Platform Security Services.
Example: SSL
For example, to support SSL policies, perform the following steps:
-
Copy the
jps-config-jse.xml
andaudit-store.xml
files from thedomain_home
/config/fmwconfig
directory, wheredomain_home
is the name and location of the domain, to a location that is accessible to the web service client. -
On the Java command line, pass the following properties:defining the JPS configuration file copied in step 1:
Define the JPS configuration file copied in step 1:
-Doracle.security.jps.config=<pathToConfigFile>
For more information, see Scenario 3: Securing a Java SE Application in Securing Applications with Oracle Platform Security Services.
Define the trust store containing the trusted certificates:
-Djavax.net.ssl.trustStore=<trustStore>
For more information, see "Setting Up the WebLogic Server in Case of a Java SE Application" in Setting Up a One-Way SSL Connection to the LDAP in Securing Applications with Oracle Platform Security Services.
Define the trust store password:
-Djavax.net.ssl.trustStorePassword=<password>
-
Parent topic: Developing Web Service Clients
Invoking a Web Service from Another WebLogic Web Service
Invoking a web service from a Jakarta EE client, such as another WebLogic web service, is similar to invoking one from a Java SE application, as described in Invoking a Web Service from a Java SE Client, with the following variation:
-
Instead of using the
clientgen
Ant task to generate the JAX-WSService
interface of the web service to be invoked, you use the<clientgen>
child element of the<jws>
element, inside thejwsc
Ant task that compiles the invoking web service. In the JWS file that invokes the other web service, however, you still use the same standard JAX-WS APIs to getService
andPortType
instances to invoke the web service operations. -
You can use the
@WebServiceRef
annotation to define a reference to a web service, as described in Sample JWS File That Invokes a Web Service.
This section describes the differences between invoking a web service from a client
in a Jakarta EE component, specifically another web service, and invoking from a
Java SE client. It is assumed that you use Ant in your development environment to
build your client application, compile Java files, and so on, and that you have an
existing build.xml
that builds a web service that you want to
update to invoke another web service.
The following list describes the changes you must make to the build.xml
file that builds your client web service, which will invoke another web service. See Sample build.xml File for a Web Service Client for the full sample build.xml
file:
-
Add a
<clientgen>
child element to the<jws>
element that specifies the JWS file that implements the web service that invokes another web service. Set the requiredwsdl
attribute to the WSDL of the web service to be invoked. Set the requiredpackageName
attribute to the package into which you want the JAX-WS client stubs to be generated.
The following list describes the changes you must make to the JWS file that implements the client web service; see Sample JWS File That Invokes a Web Service for the full JWS file example.
-
Import the files generated by the
<clientgen>
child element of thejwsc
Ant task. These include the JAX-WSService
interface of the invoked web service, as well as the Java representation of any user-defined data types used as parameters or return values in the operations of the invoked web service.Note:
If the package name set using the
packageName
attribute of<clientgen>
is set to the same package name as the client application, then you are not required to import the<clientgen>
-generated files. -
Get the
Service
andPortType
interface implementation and invoke the operation on the port as usual; see Writing the Java Client Application Code to Invoke a Web Service for details.
Parent topic: Developing Web Service Clients
Sample build.xml File for a Web Service Client
The following sample build.xml
file shows how to create a web service that itself invokes another web service; the relevant sections that differ from the build.xml
for building a simple web service that does not invoke another web service are shown in bold.
The build-service
target in this case is very similar to a target that builds a simple web service; the only difference is that the jwsc
Ant task that builds the invoking web service also includes a <clientgen>
child element of the <jws>
element so that jwsc
also generates the required JAX-WS client stubs.
<project name="webservices-service_to_service" default="all"> <!-- set global properties for this build --> <property name="wls.username" value="weblogic" /> <property name="wls.password" value="weblogic" /> <property name="wls.hostname" value="localhost" /> <property name="wls.port" value="7001" /> <property name="wls.server.name" value="myserver" /> <property name="ear.deployed.name" value="ClientServiceEar" /> <property name="example-output" value="output" /> <property name="ear-dir" value="${example-output}/ClientServiceEar" /> <property name="clientclass-dir" value="${example-output}/clientclasses" /> <path id="client.class.path"> <pathelement path="${clientclass-dir}"/> <pathelement path="${java.class.path}"/> </path> <taskdef name="jwsc" classname="weblogic.wsee.tools.anttasks.JwscTask" /> <taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask" /> <taskdef name="wldeploy" classname="weblogic.ant.taskdefs.management.WLDeploy"/> <target name="all" depends="clean,build-service,deploy,client" /> <target name="clean" depends="undeploy"> <delete dir="${example-output}"/> </target> <target name="build-service"> <jwsc srcdir="src" destdir="${ear-dir}" > <jws file="examples/webservices/service_to_service/ClientServiceImpl.java" type="JAXWS"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL" packageName="examples.webservices.complex" /> </jws> </jwsc> </target> <target name="deploy"> <wldeploy action="deploy" name="${ear.deployed.name}" source="${ear-dir}" user="${wls.username}" password="${wls.password}" verbose="true" adminurl="t3://${wls.hostname}:${wls.port}" targets="${wls.server.name}" /> </target> <target name="undeploy"> <wldeploy action="undeploy" name="${ear.deployed.name}" failonerror="false" user="${wls.username}" password="${wls.password}" verbose="true" adminurl="t3://${wls.hostname}:${wls.port}" targets="${wls.server.name}" /> </target> <target name="client"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/ClientService/ClientService?WSDL" destDir="${clientclass-dir}" packageName="examples.webservices.service_to_service.client" type="JAXWS"/> <javac srcdir="${clientclass-dir}" destdir="${clientclass-dir}" includes="**/*.java"/> <javac srcdir="src" destdir="${clientclass-dir}" includes="examples/webservices/service_to_service/client/**/*.java"/> </target> <target name="run"> <java classname="examples.webservices.service_to_service.client.Main" fork="true" failonerror="true" > <classpath refid="client.class.path"/> </java> </target> </project>
Parent topic: Invoking a Web Service from Another WebLogic Web Service
Sample JWS File That Invokes a Web Service
The following sample JWS file, called ClientServiceImpl.java
, implements a web service called ClientService
that has an operation that in turn invokes the echoComplexType
operation of a web service called ComplexService
. This operation has a user-defined data type (BasicStruct
) as both a parameter and a return value. The relevant code is shown in bold and described after the example.
package examples.webservices.service_to_service; import javax.jws.WebService; import javax.jws.WebMethod; import javax.xml.ws.WebServiceRef; // Import the BasicStruct data type, generated by clientgen and used // by the ComplexService Web Service import examples.webservices.complex.BasicStruct; // Import the JAX-WS stubs generated by clientgen for invoking // the ComplexService web service. import examples.webservices.complex.ComplexPortType; import examples.webservices.complex.ComplexService; @WebService(name="ClientPortType", serviceName="ClientService", targetNamespace="http://examples.org") public class ClientServiceImpl { // Use the @WebServiceRef annotation to define a reference to a web service. @WebServiceRef() ComplexService test; @WebMethod() public String callComplexService(BasicStruct input, String serviceUrl) { // Create a port stub to invoke ComplexService ComplexPortType port = test.getComplexPortTypePort(); // Invoke the echoComplexType operation of ComplexService BasicStruct result = port.echoComplexType(input); System.out.println("Invoked ComplexPortType.echoComplexType." ); return "Invoke went okay! Here's the result: '" + result.getIntValue() + ", " + result.getStringValue() + "'"; } }
Follow these guidelines when programming the JWS file that invokes another web service; code snippets of the guidelines are shown in bold in the preceding example:
-
Import any user-defined data types that are used by the invoked web service. In this example, the
ComplexService
uses theBasicStruct
JavaBean:import examples.webservices.complex.BasicStruct;
-
Import the JAX-WS interfaces of the
ComplexService
web service; the stubs are generated by the<cliengen>
child element of<jws>
:import examples.webservices.complex.ComplexPortType; import examples.webservices.complex.ComplexService;
-
Define a reference to a web service and an injection target for it using the
@WebServiceRef
annotation:@WebServiceRef() ComplexService service;
For more information about
@WebServiceRef
, see Defining a Web Service Reference Using the @WebServiceRef Annotation.Alternatively, you can create a proxy stub to the
ComplexService
web service, as shown below:ComplexService service = new ComplexService();
-
Return an instance of the
ComplexPortType
stub implementation by calling thegetComplexPortTypePort()
operation on the web service reference:ComplexPortType port = service.getComplexPortTypePort();
-
Invoke the
echoComplexType
operation ofComplexService
using the port you just instantiated:BasicStruct result = port.echoComplexType(input);
Parent topic: Invoking a Web Service from Another WebLogic Web Service
Configuring Web Service Clients
By default, web service clients use the web service configuration defined for the server. You can override the configuration settings used by the web service client using one of the following methods:
-
Using the Administration or WLST, if applicable. Only a subset of web service features are configurable on the client.
-
Using the
@WebServiceRef
annotation to associate the web service client with the configuration defined for the specified web service reference. The web service reference configuration is defined in theweblogic.xml
for Web containers andweblogic-ejb-jar.xml
for EJB containers. For more information about the@WebServiceRef
annotation, see Defining a Web Service Reference Using the @WebServiceRef Annotation. -
Using the
WsrmClientInitFeature
when creating a web services reliable messaging client. For more information, see Configuring Reliable Messaging on Web Service Clients.
Parent topic: Developing Web Service Clients
Defining a Web Service Reference Using the @WebServiceRef Annotation
The @WebServiceRef
annotation enables you to define a reference to a web service and attach the configuration of the web service to the client instance.
For example, in the following code excerpt, @WebServiceRef
is used to attach the configuration for ReliableEchoService
to the client's web service instance. The port that is subsequently created and initialized uses the properties defined for ReliableEchoService
service reference in the weblogic.xml
for the Web application.
package wsrm_jaxws.example; import java.xml.ws.WebService; import java.xml.ws.WebServiceRef; import wsrm_jaxws.example.client_service.*; import wsrm_jaxws.example.client_service.EchoResponse; ... @WebService public class ClientServiceImpl { @WebServiceRef(name="MyServiceRef") private ReliableEchoService service; private ReliableEchoPortType port = null; @PostConstruct public void initPort() { port = service.getReliableEchoPort(); ... } }
Example 8-1 shows an example of a weblogic.xml
file that contains a web service reference description. For information about the reliable messaging properties shown in this example, see Configuring Reliable Messaging.
Example 8-1 Example weblogic.xml File Containing Web Service Reference Description
<?xml version='1.0' encoding='UTF-8'?> <weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"> <service-reference-description> <!-- Any name you want, but use this same name on @WebServiceRef(name=<my name>). This anno goes on the service field in your client container --> <service-ref-name>MyServiceRef</service-ref-name> <!-- Use / and any path within the web app to get a local WSDL, or use a resource name as defined by the Java ClassLoader, or use an absolute/external URL you can guarantee is deployed when this web app deploys --> <wsdl-url>/WEB-INF/wsdls/ReliableEcho.wsdl</wsdl-url> <!-- One or more port-infos, one for each type of port/stub you'll create in your JWS --> <port-info> <!-- The local name of wsdl:port (not portType). The Java type for this port, when created from the @WebServiceRef JWS field, will contain, in RequestContext, the props you define below --> <port-name>ReliableEchoPort</port-name> <!-- Any prop name/value pairs you want to show up on you service stub The Java type for this port, when created from the @WebServiceRef JWS field, will contain, in RequestContext, the stub-props you define below --> <!-- RM Source Properties --> <stub-property> <name>weblogic.wsee.wsrm.BaseRetransmissionInterval</name> <value>PT30S</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.RetransmissionExponentialBackoff</name> <value>true</value> </stub-property> <!-- RM Destination Properties --> <stub-property> <name>weblogic.wsee.wsrm.RetryCount</name> <value>5</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.RetryDelay</name> <value>PT30S</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.AcknowledgementInterval</name> <value>PT5S</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.NonBufferedDestination</name> <value>true</value> </stub-property> <!-- RM Source *or* Destination Properties --> <stub-property> <name>weblogic.wsee.wsrm.InactivityTimeout</name> <value>PT5M</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.SequenceExpiration</name> <value>PT10M</value> </stub-property> </port-info> </service-reference-description> <wl-dispatch-policy>weblogic.wsee.mdb.DispatchPolicy</wl-dispatch-policy> </weblogic-web-app>
Parent topic: Developing Web Service Clients
Managing Client Identity
Web services enable you to assign any meaningful name to a client, which is represented as the client identity (client ID). This client ID is used to group statistics and other monitoring information, and for reporting runtime validations, and so on.
For on-server clients (clients running in a container within a WebLogic Server instance), the client ID can be generated in one of the following ways:
-
By the client when it initializes connection to web service port. This is the recommended approach. See Defining the Client ID During Port Initialization.
-
By the server and discovered later by the client. See Accessing the Server-generated Client ID.
Note:
Although optional, Oracle strongly recommends that you define the client ID explicitly.
The weblogic.wsee.jaxws.persistence.ClientIdentityFeature
client feature enables web service clients to set and access the web service client ID. The following table summarizes the ClientIdentityFeature
methods.
Table 8-3 Methods of ClientIdentityFeature for Setting and Accessing Client ID
Method | Description |
---|---|
|
Gets the currently defined client ID for the web service port. |
|
Sets the client ID for the web service port. In addition, you can set the client ID by passing it as an argument when instantiating the ClientIdentityFeature clientIDFeature = new ClientIdentityFeature("MyBackendServiceAsyncClient"); |
|
Disposes the client ID. If a client ID is not disposed of explicitly, it will be done when the container for the client instances that use the client ID is deactivated (for example, the host Web application or EJB is deactivated). For more information, see Client Identity Lifecycle. |
- Defining the Client ID During Port Initialization
- Accessing the Server-generated Client ID
- Client Identity Lifecycle
Parent topic: Developing Web Service Clients
Defining the Client ID During Port Initialization
To provide its client ID, the web service client can pass an instance of the ClientIdentityFeature
containing the client ID to the web service port at initialization time.
The client ID must be unique within the Web application or EJB that contains the client. It is recommended that the client ID appropriately reflect the business purpose. In order to ensure that the client ID is unique, the system prepends the names of the containing server, application, and component (Web application or EJB) to the client ID.
Note:
Care should be taken when choosing a client ID. If a client instance is created with the same client ID as an existing client instance, the two client instances will be treated as the same instance. No exception will be thrown to alert you to the duplication.
The following example demonstrates this method of specifying the client ID. It is recommended that you close the client instance once all processing has been complete, as shown.
This example is excerpted from Roadmap for Developing JAX-WS Web Service Clients.
Example 8-2 Example of Specifying the Client ID During Port Initialization
import javax.servlet.*; import javax.xml.ws.*; import weblogic.jws.jaxws.client.ClientIdentityFeature; . . . public class BestPracticeAsyncClient extends GenericServlet { ... private BackendServiceService _service; ... // Client ID ClientIdentityFeature clientIdFeature = new ClientIdentityFeature("MyBackendServiceAsyncClient"); features.add(clientIdFeature); ... _features = features.toArray(new WebServiceFeature[features.size()]); ... BackendService port = _service.getBackendServicePort(_features); ... ((java.io.Closeable)_port).close(); } }
Parent topic: Managing Client Identity
Accessing the Server-generated Client ID
Note:
As described in this section, in order to ensure that the client ID is unique, the server-generated version may be long and difficult to read. To guarantee that the client ID is presented in a user-friendly format, it is recommended that you define the client ID during port initialization, as described in Defining the Client ID During Port Initialization.
Client IDs that are generated automatically by the server use the following format:
applicationname[_applicationversion]:componentname:uniqueID
Where:
-
applicationname
—Name of the application hosting the client. -
applicationversion
—Version of the application. Only used if multiple versions of the same application is running simultaneously. -
componentname
—Name of the component (Web application or EJB) hosting the client. -
uniqueID
—Calculated based on the information that is available when the client instance is created. TheuniqueID
is constructed by choosing one of the following (whichever is available):-
Web service reference name, as defined by the
@WebServiceRef
annotation. -
[portNamespaceURI:portLocalName][:][endpointAddress]
—port name, endpoint address, or both (separated by a colon). -
Port class simple name.
The following information, when available, may also be concatenated to the
uniqueID
, separated by a colon (:), in the order presented below:-
WSDL location (minus
?wsdl
) -
Features used to create the client instance, represented by the features class name and separated by dash (-).
-
For example, assume that you deploy a web service client with the following information associated with it:
-
Application name:
example
-
Component: Web application called
BestPracticeClient
-
Port name:
http://example/BackendServicePort
-
Port class:
BackendService
-
WSDL:
jar:file:/C:/example/BackendService.war!/WEB-INF/BackendServiceService.wsdl
The server-generated client ID will be:
example:BestPracticeClient:http://example/:BackendServicePort:jar:file:/C:/example/BackendService.war!/WEB-INF/BackendServiceService.wsdl:AsyncClientTransportFeature()-ClientIdentityFeature
Each time the code is executed, assuming it is in the same containment hierarchy, the same client ID is generated. This provides a stable client ID that can be used across server VM instances and allows for asynchronous responses to be delivered to the client even after a server restart.
Note:
A given Client ID can be used from multiple locations in the client code, but care should be taken to initialize any port or Dispatch instance that uses that client ID in the same way (same features, service, and so on) as was used in any other location for that client ID.
For best practice information on the recommended approach to client instance (port or Dispatch) initialization, see Roadmap for Developing JAX-WS Web Service Clients.
The following example demonstrates how to access the server-generated client ID. This example is excerpted from Table 7-1.
Example 8-3 Example of Accessing the Server-generated Client ID
... // Create a port without explicitly defining the client ID to view the client ID that is // generated automatically. ClientIdentityFeature dummyClientIdFeature = new ClientIdentityFeature(null); BackendService dummyPort = _service.getBackendServicePort(dummyClientIdFeature); System.out.println("Generated Client Identity is: " + dummyClientIdFeature.getClientId()); // Best Practice: Explicitly close client instances when processing is complete. // If not closed, the port will be closed automatically when it goes out of scope. // Note, this client ID will remain registered and visible until our // container (Web application) is undeployed. ((java.io.Closeable)dummyPort).close();
Parent topic: Managing Client Identity
Client Identity Lifecycle
A client ID is registered with the web services runtime when the first client instance (port or Dispatch instance) using the client ID is created. Any asynchronous response endpoint associated with the client instances is also tracked along with the registered client ID.
The client ID remains registered until one of the following occurs:
-
The client ID is explicitly disposed using the
dispose()
method onClientIdentityFeature
, as described in Table 8-3. -
The container for the client instances that use the client ID is deactivated (for example, the host Web application or EJB is deactivated).
Parent topic: Managing Client Identity
Using a Proxy Server When Invoking a Web Service
You can use a proxy server to proxy requests from a client application to an application server (either WebLogic or non-WebLogic) that hosts the invoked web service. You typically use a proxy server when the application server is behind a firewall. You can specify the proxy server in your client application using Java system properties. There are two ways to specify the proxy server in your client application: programmatically using the WebLogic ClientProxyFeature
API or using system properties.
- Using the ClientProxyFeature API to Specify the Proxy Server
- Using System Properties to Specify the Proxy Server
Parent topic: Developing Web Service Clients
Using the ClientProxyFeature API to Specify the Proxy Server
You can programmatically specify within the Java client application itself the details of the proxy server that will proxy the web service invoke using the weblogic.wsee.jaxws.proxy.ClientProxyFeature
API. See ClientProxyFeature in Java API Reference for Oracle WebLogic Server.
The proxy server settings defined by the ClientProxyFeature
override the settings defined at the JVM-level, as described in Using System Properties to Specify the Proxy Server.
Note:
The ClientProxyFeature
configures the port for WebLogic HTTP over SSL. It is recommended that you configure SSL for WebLogic Server. For more information, see Configuring SSL in Administering Security for Oracle WebLogic Server.
The ClientProxyFeature
setUseSunHttpHandler
method forces WebLogic Server to use the Sun HTTP implementation on a per-connection-request basis. You can instead use the -DUseSunHttpHandler=true
WebLogic Server startup configuration option, which applies the setting for the WebLogic Server instance.
You can configure the proxy server information using the ClientProxyFeature
and pass the feature as an argument when creating the web service port, as shown in the following example.
Example 8-4 Pass ClientProxyFeature as an Argument When Creating Port
package examples.webservices.simple_client; import weblogic.wsee.jaxws.proxy public class Main { public static void main(String[] args) { ComplexService test = new ComplexService(); ClientProxyFeature cpf = new ClientProxyFeature(); cpf.setProxyHost("localhost"); cpf.setProxyPort(8888); cpf.setProxyUserName("proxyu"); cpf.setProxyPassword("proxyp"); ComplexPortType port = test.getComplexPortTypePort(cpf); BasicStruct in = new BasicStruct(); in.setIntValue(999); in.setStringValue("Hello Struct"); BasicStruct result = port.echoComplexType(in); System.out.println("echoComplexType called. Result: " + result.getIntValue() + ", " + result.getStringValue()); } }
Alternatively, you can configure the proxy server information after the port is created, as shown in the following example. In this case, you execute the attachsPort()
method to attach the ClientProxyFeature
to the existing port.
Example 8-5 Configuring the ClientProxyFeature After Creating the Port
package examples.webservices.simple_client; import weblogic.wsee.jaxws.proxy public class Main { public static void main(String[] args) { ComplexService test = new ComplexService(); ComplexPortType port = test.getComplexPortTypePort(); ClientProxyFeature cpf = new ClientProxyFeature(); cpf.setProxyHost("localhost"); cpf.setProxyPort(8888); cpf.setProxyUserName("proxyu"); cpf.setProxyPassword("proxyp"); cpf.attachsPort(port); BasicStruct in = new BasicStruct(); in.setIntValue(999); in.setStringValue("Hello Struct"); BasicStruct result = port.echoComplexType(in); System.out.println("echoComplexType called. Result: " + result.getIntValue() + ", " + result.getStringValue()); } }
If after configuring the ClientProxyFeature
and attaching it to the port you want to disable the client proxy settings, you set the proxy port to a negative value. For example:
Example 8-6 Disabling Client Proxy Settings
. . . ClientProxyFeature cpf = new ClientProxyFeature(); cpf.setProxyPort(-1);\ cpf.attachsPort(port); . . .
Parent topic: Using a Proxy Server When Invoking a Web Service
Using System Properties to Specify the Proxy Server
To use system properties to specify the proxy server, write your client application in the standard way, and then specify Java system properties when you execute the client application.
The following table summarizes the Java system properties.
Note:
In this case, the proxySet system property must not be set. If the proxySet system property is set to (proxySet=false), proxy properties will be ignored and no proxy will be used.
Table 8-4 Java System Properties Used to Specify Proxy Server
Property | Description |
---|---|
http.proxyHost=proxyHost or https.proxyHost=proxyHost |
Name of the host computer on which the proxy server is running. Use https.proxyHost for HTTP over SSL. |
http.proxyPort=proxyPort or https.proxy.Port=proxyPort |
Port to which the proxy server is listening. Use https.proxyPort for HTTP over SSL. |
http.non.proxyHosts=hostname | hostname | ... |
List of hosts that should be reached directly, bypassing the proxy. Separate each host name using a | character. This property applies to only HTTP. |
https.nonProxyHosts=hostname | hostname | ... |
List of hosts that should be reached directly, bypassing the proxy. Separate each host name using a | character. This property applies to only HTTPS. |
The following excerpt from an Ant build script shows an example of setting Java system properties when invoking a client application called clients.InvokeMyService
:
<target name="run-client"> <java fork="true" classname="clients.InvokeMyService" failonerror="true"> <classpath refid="client.class.path"/> <arg line="${http-endpoint}"/> <jvmarg line= "-Dhttp.proxyHost=${proxy-host} -Dhttp.proxyPort=${proxy-port} -Dhttp.nonProxyHosts=${myhost}" /> </java> </target>
Parent topic: Using a Proxy Server When Invoking a Web Service
Client Considerations When Redeploying a Web Service
WebLogic Server supports production redeployment, which means that you can deploy a new version of an updated WebLogic web service alongside an older version of the same web service.
WebLogic Server automatically manages client connections so that only new client requests are directed to the new version. Clients already connected to the web service during the redeployment continue to use the older version of the service until they complete their work, at which point WebLogic Server automatically retires the older web service.
You can continue using the old client application with the new version of the web service, as long as the following web service artifacts have not changed in the new version:
-
WSDL that describes the web service
-
WS-Policy files attached to the web service
If any of these artifacts have changed, you must regenerate the JAX-WS stubs used by the client application by re-running the clientgen
Ant task.
For example, if you change the signature of an operation in the new version of the web service, then the WSDL file that describes the new version of the web service will also change. In this case, you must regenerate the JAX-WS stubs. If, however, you simply change the implementation of an operation, but do not change its public contract, then you can continue using the existing client application.
Parent topic: Developing Web Service Clients
Client Considerations When Web Service and Client Are Deployed to the Same Managed Server
If a web service and client are deployed to the same Managed Server, and one of the following is true:
-
The web service client uses the
@WebServiceRef
annotation, but does not specify a value for thewsdlLocation
element. -
The web service client uses the
wsdlLocation
element of the@WebServiceRef
annotation to refer to the live WSDL location (for example,@WebServiceRef(wsdlLocation="http://xyz.com/myService?WSDL")
), as opposed to a WSDL that is packaged with the web service application (for example,@WebServiceRef(wsdlLocation="myService.wsdl")
).
Then, when you restart the Managed Server on which the web service and client are deployed, the web service client may fail to redeploy, regardless of the deployment order, because the applications are deployed initially in administration mode, and later transition to production mode to accept HTTP requests. In this situation, you must restart the application manually once the server has restarted.
If a web service and client are deployed to the same Managed Server, to avoid this situation, it is recommended that you package the WSDL as part of the web service application and refer to the packaged version from the @WebServiceRef
annotation.
Parent topic: Developing Web Service Clients