WebLogic Web Service Clients


WebLogic Web Service Clients

This section focuses on a few types and styles of Web service clients that can consume WebLogic Web services. The treatment is certainly not exhaustive, but it does provide a few starting points.

Web Service Client Models

JAX-RPC defines three programmatic client interaction models, which WebLogic Server supports. They are described in the following sections.

Static

The most simple among the client modes, static invocation is best suited for use in situations in which the Web service is known and can be bound at development time. The implication is that there is no requirement to switch to another, albeit similar, Web service at runtime.

JAX-RPC prescribes a pattern for generating service-specific client stubs (which collectively act as the smart proxy shown in Figure 29.12) that are bound into the client at build time. These stubs are essentially abstractions to the service and port elements of the WSDL file:

  • ServiceNamePort Specifies a client stub representing the WSDL port element, where all operations advertised for that port can be invoked

  • ServiceName_Impl Represents the WSDL service but also acts as a cabinet for retrieving the above port object

In the static client model, the Smart Proxy box is specifically composed of these stubs, as shown in Figure 29.17. The stubs shown here are for a specific Web service named TaxService .

Figure 29.17. Service-specific stubs in a static client.

graphics/29fig17.gif

WebLogic Server follows this JAX-RPC prescription by providing tools that can take a known Web service description, either described by a provider EJB or an existing WSDL, and generate these stubs. These tools are discussed in detail in Chapter 30. Listing 29.2 shows the service description (WSDL) for an over-simplified sales tax Web service called TaxService . It supports one operation called calculateTax , which takes two string arguments, the Product Category of the item to be taxed and Postal/ZIP Code of the tax jurisdiction, and finally returns the sales tax percentage.

Listing 29.2 Tax Web Service WSDL File
 <?xml version="1.0" encoding="utf-8"?> <definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://www.bea.com/servers/samples/examples/webservices/basic" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://www.bea.com/servers/samples/examples/webservices/basic" xmlns="http://schemas.xmlsoap.org/wsdl/"> <message name="calculateTax"> <part name="category" xmlns:partns="http://www.w3.org/2001/XMLSchema" type="partns:string" /> <part name="zip" xmlns:partns="http://www.w3.org/2001/XMLSchema" type="partns:string" /> </message> <message name="calculateTaxResponse" > <part name="result" xmlns:partns="http://www.w3.org/2001/XMLSchema" type="partns:string" /> </message> <portType name="TaxServicePort" > <operation name="calculateTax" > <input message="tns:calculateTax" /> <output message="tns:calculateTaxResponse" /> </operation> </portType> <binding name="TaxServicePortSoapBinding" type="tns:TaxServicePort" > <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> <operation name ="calculateTax" > <soap:operation soapAction="" style="rpc" /> <input> <soap:body use="encoded" namespace="http://www.bea.com/servers/ samples/examples/webservices/basic" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> </input> <output> <soap:body use="encoded" namespace="http://www.bea.com/servers/ samples/examples/ webservices /basic" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> </output> </operation> </binding> <service name="TaxService" > <documentation>todo: add your documentation here</documentation> <port name="TaxServicePort" binding="tns:TaxServicePortSoapBinding"> <soap:address location="http://localhost:7001/taxws/TaxService?WSDL"/> </port> </service> </definitions> 

The client code snippet looks like this:

 
 TaxService_Impl ws = new TaxService Impl("http://localhost:7001/taxws/TaxService"); TaxServicePort port = ws.get TaxServicePort(); port.calculateTax("4A", "80302"); 

Both the TaxService_Impl and TaxServicePort classes can be generated by WebLogic Server. These stubs cannot be used to represent any other Web service except the one whose service description was used to generate them. In other words, the service cannot be changed at execution time; hence, it is considered static.

Dynamic (with WSDL)

The Dynamic client model, also known as the Dynamic Invocation Interface (DII) , allows you to invoke a service whose interface types may not be known until runtime. Examples of this situation might be

  • If you're using UDDI to discover and integrate a Web service at runtime

  • If static stubs are not available at build time

Although this mode is much more flexible, it is also more complex and likely more difficult to develop, debug, and test. It is recommended that you use this invocation style with caution and only if absolutely necessary.

Figure 29.18 shows the client stack for dynamic service invocation. Here the smart proxy is composed of three more-generic client proxies.

Figure 29.18. Generic stubs in a dynamic client.

graphics/29fig18.gif

In the DII mode, the client proxies are no longer service specific as they are in the static client scenario. Here, you use JAX-RPCprescribed generic classes for invoking a Web service, which include (all in package javax.xml.rpc ):

  • Service Acts as a generic stub for a Web service and declares the operations or methods that a client may invoke on the service

  • ServiceFactory Acts as a factory class for creating Service instances

  • Call Represents a specific operation advertised by a service and is used as a handle for invoking the operation

Again, these classes can be used to invoke any Web service, not just this tax service example.

The steps for dynamic invocation are as follows:

  1. Establish a service factory in the Web service runtime.

  2. Instantiate a service factory.

  3. Indicate which specific port, service, and operation you are trying to invoke. You do so by using references into the WSDL file via the XML qualified name construct, mapped to Java as the QName class.

  4. Given the service WSDL and port QName, obtain a Service instance from the service factory.

  5. Given the port and operation, obtain a Call instance for the operation to be invoked, from the Service instance.

  6. Invoke the operation. You pass in an array whose elements are of type Object . Each object instance represents an argument to the service operation, in the same order as defined in its WSDL. For Web service operations that take primitive Java types, you can still pass in its equivalent wrapper classes in the object array argument. The built-in serializers and deserializers are smart enough, by way of reflection, to divine the appropriate conversions.

The code snippet shown in Listing 29.3 realizes the preceding steps (where appropriate the step number is mentioned in commentary ).

Listing 29.3 Code Representing the Steps for Dynamic Invocation
 // STEP 1: Setup the global JAX-RPC service factory System.setProperty("javax.xml.rpc.ServiceFactory", "weblogic.webservice. core .rpc.ServiceFactoryImpl"); // STEP 2: create service factory ServiceFactory factory = ServiceFactory.newInstance(); // STEP 3: define qnames String targetNamespace = "http://localhost:7001/..."; QName serviceName = new QName(targetNamespace, "TaxService"); QName portName = new QName(targetNamespace, "TaxServicePort"); QName operationName = new QName(targetNamespace, "calculateTax"); URL wsdlLocation = new URL("http://localhost:7001/taxws/TaxService?WSDL"); // STEP 4: create service Service service = factory.createService(wsdlLocation, serviceName); // STEP 5: create call Call call = service.createCall(portName, operationName); // Build args or custom types, if any // STEP 6: invoke the operation result = call.invoke(new Object[] {"4A", "80302"}) ; 
More on QNames

A qualified name (QName) construct is an unambiguous reference to an XML data itemin this case, a WSDL item. A qualified name is made up of two parts : a namespace qualifier and a local name . The first argument to the QName constructor is the namespace of the WSDL item. In the case of the TaxService WSDL, all the service, port, and operation items use the default namespace for the XML file: the TargetNamespace attribute of the namespace definitions element. The second argument in this case is the WSDL data item, which is a local name in the WSDL file.

At the risk of " stating the obvious," Table 29.2 shows how each Qname value is set.

Table 29.2. How Each QName Value Is Set

QName For

WSDL Data Item

Example

service

name attribute of the service element

<service name="TaxService">

port

name attribute of the port element ( port is a sub-element of service )

port <port name="TaxServicePort"

operation

name attribute of the operation element ( operation is a subelement of portType )

<operation name="calculateTax">

The WSDL file for this sample tax service is shown in Listing 29.2.

Dynamic (Without WSDL)

You can also invoke a Web service dynamically without having access to a WSDL file at runtime. You still need to consult the WSDL file contents at development time, to glean the information needed for dynamic clients, and more. You need to explicitly set more WSDL information in the Call object, such as operation parameters and endpoint address. As shown in Listing 29.4, the steps for this task are similar to the dynamic client using known WSDL information, with just some additional code (steps 6 and onward) that builds up the Call object prior to invocation.

Listing 29.4 Code Snippet for Dynamic Client That Does Not Use WSDL File
 // STEP 1: Setup the global JAX-RPC service factory System.setProperty("javax.xml.rpc.ServiceFactory", "Weblogic.Webservice.core.rpc.ServiceFactoryImpl"); // STEP 2: create service factory ServiceFactory factory = ServiceFactory.newInstance(); // STEP 3: define qnames String targetNamespace = "http://localhost:7001/..."; QName serviceName = new QName(targetNamespace, "TaxService"); QName portName = new QName(targetNamespace, "TaxServicePort"); QName operationName = new QName(targetNamespace, "calculateTax"); // STEP 4: create service Service service = factory.createService(serviceName); // STEP 5: create call Call call = service.createCall(); // Build args or custom types, if any // STEP 6: set port and operation name call.setPortTypeName(portName); call.setOperationName(operationName); // STEP 7: add parameters call.addParameter("category", new QName("http://www.w3.org/2001/XMLSchema", "string"), ParameterMode.IN); call.addParameter("zip", new QName("http://www.w3.org/2001/XMLSchema", "string"), ParameterMode.IN); call.setReturnType(new QName("http://www.w3.org/2001/XMLSchema", "string"), String); // STEP 8: set end point address call.setTargetEndpointAddress("http://localhost:7501/taxws/TaxService"); // STEP 9: call service result = call.invoke(new Object[] {"4A", "80302"}) ; 

A caveat to keep in mind is that a dynamic client is not completely dynamic because, as you may have noticed, the client still needs to presume or hard-code the Web service method's signature (order and type of arguments and return type). It does allow you to switch Web services at execution time, but for such Web services to be interchangeable, they must all have the same signatures. A more realistic scenario occurs when a Web service is being enhanced (like new methods being added) or versioned. An existing client accustomed to using the version 1 service can just point to a different URL to get the new improved version 2 service ( assuming backward compatibility).

InOut Parameters

JAX-RPC also defines a mechanism for supporting output arguments in Web service methods, that is, passing result information back to the client via the argument list. This is a convenient feature, allowing you to define a Web service method that returns multiple values without needing to define and use a complex type. WSDL 1.1 adds support for out and inout arguments via the following rules:

  • If a part name appears in only the output message, it is an out parameter.

  • If a part name appears in both the input and output message, with the same type, it is an inout parameter.

The javax.xml.rpc.holders.Holder interface class was created solely for affecting out or inout arguments. JAX-RPC defines a holder implementation class for each of its supported data types, which are as follows. (This list is not exhaustive; refer to the JAX-RPC specifications for the complete list.)

  • BigDecimalHolder , BigIntegerHolder

  • BooleanHolder , BooleanWrapperHolder

  • ByteArrayHolder

  • StringHolder

  • ByteHolder , ByteWrapperHolder

  • IntegerHolder , IntegerWrapperHolder

  • FloatHolder , FloatWrapperHolder

Note the pattern for primitives and their corresponding wrapper classes: xxx Holder represents the primitive type xxx , and xxx WrapperHolder represents its wrapper class. For instance, the IntegerHolder class represents the primitive type int , and the IntegerWrapperHolder class represents the Integer class. Table 29.3 lists the Holder classes supported by WebLogic Server 7.0.

Table 29.3. List of Holder Classes Provided by WebLogic Server 7.0

Built-in Holder Class

Type That It Holds

Javax.xml.rpc.holders.BooleanHolder

boolean

Javax.xml.rpc.holders.ByteHolder

byte

Javax.xml.rpc.holders.ShortHolder

short

Javax.xml.rpc.holders.IntHolder

int

Javax.xml.rpc.holders.LongHolder

long

Javax.xml.rpc.holders.FloatHolder

float

Javax.xml.rpc.holders.DoubleHolder

double

Javax.xml.rpc.holders.BigDecimalHolder

java.math.BigDecimal

Javax.xml.rpc.holders.BigIntegerHolder

java.math.BigInteger

Javax.xml.rpc.holders.ByteArrayHolder

byte[]

Javax.xml.rpc.holders.CalendarHolder

java.util.Calendar

Javax.xml.rpc.holders.QnameHolder

javax.xml.namespace.QName

Javax.xml.rpc.holders.StringHolder

java.lang.String

In other words, a client wishing to invoke a Web service method that has output arguments must pass the appropriate Holder class for each output parameter in its signature. For example, say you have a StockTrader Web service with a buy method that takes three arguments:

 
 Buy (  in  ticker,  inout  numOfShares,  out  sharePrice) 

where

  • ticker is an input parameter representing the stock to purchase.

  • numOfShares is an input parameter indicating the number of shares to purchase, but on return it will be set to the actual number of shares bought; therefore, it is an inout parameter.

  • sharePrice is undefined during invocation but on return will be set to the actual price of each share purchased; therefore, it is an out parameter.

Listing 29.5 shows the client code for invoking this method (using static proxies).

Listing 29.5 Client Code for Invoking the buy Method
 import javax.xml.rpc.holders.*; public class Main{ public static void main(String[] args) throws Exception { // Get the Web service StockTrader_Impl trader = new StockTrader_Impl(WSDLuri); StockTraderPort traderPort = trader .getStockTraderPort(); // Define the Holder objects for inout and out parameters IntHolder numShares = new IntHolder(100); FloatHolder sharePrice = new FloatHolder(); // Invoke the Web service traderPort.buy("BEAS", numShares, sharePrice); // Print out values of inout & out parameters System.out.println("I ordered to buy 100 shares of BEAS " + "and actually got " + numShares.value + " shares at " + sharePrice.value " dollars per share."); } } 

Each Holder class must have a constructor that takes an initial value argument of the type that the Holder class represents. It also must have a public field named value , again of the type that the Holder class represents.

WebLogic Platform 7.0 ships Holder implementation classes for the standard set of supported built-in Java types. The WebLogic Web service tool serviceGen also automatically generates Holder classes for your user -defined types, whether or not you use output parameters. In the latter case, the classes are extraneous and do not affect your Web service in any way.



BEA WebLogic Platform 7
BEA WebLogic Platform 7
ISBN: 0789727129
EAN: 2147483647
Year: 2003
Pages: 360

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net