Introduction
Axis2 is the next generation of Apache Axis. Although supported by the Axis 1.x handler model, AXIS2 is more flexible and scalable to the new architecture. Axis2 is newly written based on the new architecture and does not use the Axis 1.x common code. The motivation to support development Axis2 is to explore more modular, more flexible, and more efficient architectures that can easily be plugged into implementations of other relevant WEB service standards and protocols such as Ws-security, ws-reliablemessaging, and so on.
AXIS2 features include: A new core XML processing model named AXIOM (AXIs Object mOdel,axis object model) supports IN-ONLY and in-out message exchange modes (M EP) blocking and Non-blocking client APIs (application programming interfaces) support built-in WEB service Addressing (ws-addressing) support for XMLBeans data binding new deployment model supports Hypertext Transfer Protocol (HTTP), Simple Mail Transfer Protocol (SMTP), and Transmission Control Protocol (TCP), etc. transport protocol
This series of articles is based on the AXIS2 1.0 version. You can get the latest version of Axis2 on the Apache website.
Axis Architecture Overview
Figure 1. AXIS2 Architecture
The AXIS2 architecture separates logic from state; This allows logic to be performed in parallel threads. The static state and dynamic state of the service and the invocation are stored separately in the Description and context classes. The AXIS2 architecture is implemented using 7 separate modules.Information Model:This module manages the state of the SOAP engine. The model defines a set of classes for storing states, while the engine manages the lifecycle of these information objects. The information model contains two classes for storing states. The Description class stores data that is inherently static and exists throughout the lifecycle of an Axis engine instance (such as transport, service, and Operation configuration). The context class holds dynamic information such as the current request and response SOAP messages, from addresses, to addresses, and other elements that are valid in the invocation contexts.XML processing Model:AXIS2 introduces a new model called AXIOM, which is used to process SOAP messages. AXIOM uses StAX (streaming API for XML) to parse XML. StAX is a standard flow-Pull parser Java™api. AXIOM is very sophisticated and does not slow down the construction of XML information sets-in other words, objects are created only when absolutely necessary. Overall, AXIOM and Axis2 occupy less memory than Axis 1.SOAP processing Model:The AXIS2 architecture defines two pipelines (or streams), called inpipe (Inflow) and outpipe (outflow), which are used to process server-side request messages and response messages, respectively. On the client side, the two pipes are reversed-in other words, the SOAP request messages flow through the outpipe, and the response messages flow through the inpipe. A pipe or stream contains a series of stages-separated handlers. The phases are executed in a predefined order, as shown in Figure 1 above. In addition to predefined stages and processing assemblies, users can configure user stages and related handlers at the action level, service level, or global level. The handler acts as an interceptor for the SOAP message and can handle the Header or body of the SOAP message. Inpipe is configured through the following stages: Transportin predispatch Dispatch postdispatch policydetermination User Phases Message Validation we will The above phases are described in detail in part 2nd of this series of articles. The request message arrives at Messagereceiver after all the stages configured through Inpipe, and then the actual service implementation is invoked by Messagereceiver. The outpipe of the server contains the following phases: Message initialization Policy Determination user phases Messageout users configured the stage in the user phase of both pipelines (user phases) Part. If an error occurs during the execution of these pipelines, the errors are passed through the Infaultpipe or Outfaultpipe pipeline. When a Fault message is received, the infaultpipe is invoked on the client, and Outfaultpipe is invoked on the server side if a call causes an error to be sent to the client. Users can add handlers to predefined stages and are configured in the order in which they are run.Deployment module:This module configures the Axis engine and deploys services and modules. The Axis2.xml (in Webapps/axis2/web-inf) contains the global configuration of the Axis2 engine, including: Global module global Modules) a transport (receivers) user Stage definitions (User phase definitions) The configuration of each service is contained in the Services.xml file for the service archive. This file will be discussed in detail later in this article.WSDL and code generation:This module generates the client stub and the server framework code from the WSDL file. The AXIS2 code generator emits an XML file that uses the correct XML stylesheet to generate code in the language that you want.Client API:The AXIS2 client API invokes operations that follow the in-only and in-out message patterns defined by WSDL 2.0. The client API supports blocking and non-blocking calls for in-out operations.Transmission:This module contains handlers that interact with the transport layer. There are two types of transport handlers: Transportlistener and Transportsender. Transportlistener receives SOAP messages from the transport layer and then passes them to inpipe for processing. Transportsender sends a SOAP message received from Outpipe by specifying a transport. AXIS2 provides HTTP, SMTP, and TCP handlers. For HTTP transmissions, the Axisservlet on the server side and a simple stand-alone HTTP server on the client (provided by AXIS2) Act as transportreceiver.
|
Back to the top of the page |
|
Deploy AXIS2
Deployment Axis2 is as simple as deploying Axis 1. First, locate the Axis2 Web application Axis2.war in the WebApps directory of the AXIS2 binary distribution package. Deploy this war file in the Servlet container. In Tomcat, if you have set Unpackwars to True in the server configuration, you can deploy AXIS2 only by copying Axis2.war to the $TOMCAT _home/webapps directory. Please start Tomcat now and Access Http://localhost:<port>/axis2. The Axis2 Welcome page appears and clicks the Validate link on this page. You should arrive at the Axis2 Happiness pagewithout any errors.
|
Back to the top of the page |
|
Development StockQuoteService
Here's how to develop StockQuoteService using in-only subscribe () and In-out getquote (). The subscribe () operation will subscribe to the hourly quote for the specified code, while GetQuote () will get the current quote for the specified code name.
The following listing 1 is an implementation example of StockQuoteService:
Listing 1. StockQuoteService Implementation
Package stock; Import Org.apache.axiom.om.OMAbstractFactory; Import org.apache.axiom.om.OMElement; Import Org.apache.axiom.om.OMFactory; Import Org.apache.axiom.om.OMNamespace;
public class StockQuoteService {
public void Subscribe (omelement in) { String symbol = In.gettext (); SYSTEM.OUT.PRINTLN ("Subscription Request for symbol =" +symbol); Put the actual subscribe code here ... }
Public omelement GetQuote (omelement in) {
Get the symbol from request String symbol = In.gettext ();
int quote = 0; if (Symbol.equals ("IBM")) { quote = 100; } Put more quotes ...
Create response Omfactory FAC = omabstractfactory.getomfactory (); Omnamespace omns = Fac.createomnamespace ( "Http://www.developerworks.com/example", "example"); Omelement resp = fac.createomelement ("Getquoteresponse", omns); Resp.settext (string.valueof (quote)); Return resp; } }
|
The OM child package in Axis2 moves from the Axis2 package in the V1.0 version to the axiom package.
|
Back to the top of the page |
|
Deployment Services
Deployment Descriptor
In Axis2, the service deployment information is contained in the Services.xml file (in the previous version of 0.92, this file is named Service.xml). For the above StockQuoteService, the service deployment descriptor is similar to listing 2 below.
Listing 2. Services.xml
<service name= "StockQuoteService" > <parameter name= "ServiceClass" locked= "Xsd:false" > Stock. StockQuoteService </parameter>
<operation name= "GetQuote" > class= "Org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> </operation>
<operation name= "Subscribe" > class= "Org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/> </operation> </service>
|
The Name property of the service defines the names of the services. Axis2 uses the name of the service to create the endpoint address of the service, such as http://localhost:<port>/axis2/services/<nameofservice>. Therefore, for StockQuoteService, the service endpoint is http://localhost:<port>/axis2/services/StockQuoteService. The ServiceClass parameter specifies the service implementation class.
Each <operation> element defines the configuration of an operation in the service. The <operation> Name property should be set to the name of the method in the service implementation class. The Messagereceiver element defines the message sink that is used to handle this operation. AXIS2 provides two built-in messagereceivers;org.apache.axiom.receivers.rawxmlinonlymessagereceiver without data binding for in-only and in-out operations for In-only operation, while Org.apache.axiom.receivers.RawXMLINOutMessageReceiver is used for in-out operations. If Messagereceiver is not specified, AXIS2 will attempt to use Org.apache.axiom.receivers.RawXMLINOutMessageReceiver as the default messagereceiver. The rawxml message sink passes the <Body> content of the incoming SOAP message to the service implementation as Omelement (Omelement is the AXIOM abbreviation for the XML element). This action should be the XML content contained in the <Body> element that returns the SOAP response as Omelement. This explains why subscribe () and getquote () operations use and return omelement.
Services.xml can also contain multiple services that are divided into servicegroup.
packaged
The Axis 2 service is packaged as Axis Archive (. aar). This is a jar file (created using a jar or zip utility), and a Services.xml file is packaged in the archived Meta-inf directory. StockQuoteService will have the following structure when packaged into Stockquoteservice.aar:
./stock/stockquoteservice.class ./meta-inf/services.xml |
Prepackaged StockQuoteService Archives can be found in the downloads section of this article.
Because StockQuoteService does not use RPC-mode message sinks, the WSDL file cannot be generated automatically in STOCKQUOTESERVICE?WSDL mode, and the solution is to generate the corresponding WSDL file by hand or by other tools, Package it in a stockquoteservice.aar. At this point StockQuoteService packaged into Stockquoteservice.aar will have the following structure:
./stock/stockquoteservice.class ./meta-inf/services.xml ./meta-inf/services.wsdl |
Deploy
Deploying a service in Axis2 is fairly straightforward, simply by copying the. aar file to the Axis2/web-inf/services directory in the Axis2 Web application in the servlet container. For Tomcat, this position is $TOMCAT _home/webapps/axis2/web-inf/services.
Another good way to deploy a service is to use the Upload Service tool in the AXIS2 Management console. Please go to HTTP://LOCALHOST:<PORT>/AXIS2 and select Administration link. Enter the username and password admin/axis2, and then log in. (You can configure the username/password in axis2.xml.) Select the Upload Service link in the Tools section, select the . AAR file, and then click Upload. It's that simple. If the upload succeeds, the system displays a green success message. The service is deployed and can be invoked at any time. This feature is handy if you want to deploy services on a remote AXIS2 server.
|
Back to the top of the page |
|
Using Web services through AXIS2
The attributes of a WEB service invocation are determined by the MEP, the transport protocol, and the synchronization and/or asynchronous behavior of the client API. Axis2 currently supports the in-only and in-out MEP defined by WSDL 2.0. The AXIS2 client API supports synchronous and asynchronous calls to services. Provides asynchronous behavior at the API level and at the transport level when the in-out operation is invoked. API-level asynchrony is obtained by rollback, which uses a transport connection to transfer requests and responses simultaneously (for example, to transfer requests and responses over an HTTP connection). In transport-level asynchrony, requests and receive responses are sent separately using different transport connections, such as when using SMTP for transmission.
The following is the details of invoking In-only and in-out operations using the AXIS2 client API.
Invoke In-only Operation
The Org.apache.axis2.clientapi.MessageSender class is used to invoke the in-only operation (as shown in Listing 3 below), while the in-only operation invokes the StockQuoteService subscribe () operation.
Listing 3. Invoke the in-only operation
try{ EndpointReference Targetepr = new EndpointReference ( "Http://localhost:8080/axis2/services/StockQuoteService");
Make the request message Omfactory FAC = omabstractfactory.getomfactory (); Omnamespace omns = Fac.createomnamespace ( "Http://www.developerworks.com/example", "example"); Omelement payload = fac.createomelement ("subscribe", omns);
Send the request Messagesender Msgsender = new Messagesender (); Msgsender.setto (TARGETEPR); Msgsender.setsendertransport (constants.transport_http); Msgsender.send ("subscribe", payload); }catch (Axisfault axisfault) { Axisfault.printstacktrace (); }
|
Messagesender.send () sends the request message and returns it immediately. The transport to be used is specified by Messagesender.setsendertransport (). This example sends messages over HTTP.
Invoke In-out Operation
Using the Org.apache.axis2.clientapi.Call class makes it easy to invoke in-out operations. When the in-out operation is invoked, this call class supports the following 4 modes:
blocking single transfer mode : This is the easiest way to invoke the In-out Web service operation. The service invocation is blocked until the operation completes and receives a response or error. It uses a transport connection to send and receive responses at the same time, as shown in Listing 4 below.
Listing 4. Blocking single transfer mode
try {
EndpointReference Targetepr = new EndpointReference ( "Http://localhost:8080/axis2/services/StockQuoteService");
Create Request Message Omfactory FAC = omabstractfactory.getomfactory (); Omnamespace omns = Fac.createomnamespace ( "Http://www.developerworks.com/example", "example"); Omelement payload = fac.createomelement ("GetQuote", omns); Payload.settext ("IBM");
Create the call Call call = new Call (); Call.setto (TARGETEPR);
Call.settransportinfo (Constants.transport_http, Constants.transport_http, false); Invoke Blocking Omelement result = call.invokeblocking ("GetQuote", payload);
System.out.println ("Quote =" +result.gettext ()); }catch (Axisfault axisfault) { Axisfault.printstacktrace (); }
|
The first part of the code uses AXIOM to create the request message. Call.settransportinfo () sets the transport for sending requests and obtaining responses. The Boolean parameter of the Call.settransportinfo () operation indicates whether to use a different transport connection to send the request and receive the response separately. In this case, you are required to send a request and receive a response with an HTTP connection.
non-blocking single transfer mode : In this call mode, only one of the following transport connections is used to obtain non-blocking calls. This behavior is required if you want to complete more than one Web service invocation in a client application, and you do not want each call to block the client. At this point, if the response is available, the call returns immediately and the client is rolled back, as shown in Listing 5 below.
Listing 5. Non-blocking single transfer mode
try { EndpointReference Targetepr = new EndpointReference ( "Http://localhost:8080/axis2/services/StockQuoteService");
Create the request Omfactory FAC = omabstractfactory.getomfactory (); Omnamespace omns = Fac.createomnamespace ( "Http://www.developerworks.com/example", "example"); Omelement payload = fac.createomelement ("GetQuote", omns); Payload.settext ("IBM");
Create the call Call call = new Call (); Call.setto (TARGETEPR);
Set the transport info. Call.settransportinfo (Org.apache.axis2.Constants.TRANSPORT_HTTP, Org.apache.axis2.Constants.TRANSPORT_HTTP, false);
Callback to handle the response
Callback Callback = new Callback () {
public void OnComplete (asyncresult result) { System.out.println ("Quote =" + Result.getresponseenvelope (). GetBody (). Getfirstelement () . GetText ()); }
public void ReportError (Exception e) { E.printstacktrace (); } };
Invoke Non Blocking
Call.invokenonblocking ("GetQuote", payload, callback);
Wait till the callback receives the response.
while (!callback.iscomplete ()) { Thread.Sleep (1000); }
Call.close (); catch (Axisfault Axisfault) { Axisfault.printstacktrace (); catch (Exception ex) { Ex.printstacktrace (); }
|
The Call.invokenonblocking () method returns immediately without blocking. Call.invokenonblocking () takes a Org.apache.axis2.clientapi.CallBack object, which is triggered if the response is from a service. CallBack has two abstract methods OnComplete (Asynchresult) and ReportError (Exception), which need to be implemented by specific CallBack classes. After the service call completes normally, the Axis2 engine invokes the OnComplete () method. After you obtain an error message from the server, call the Callback ReportError () method. Callback.iscomplete () indicates whether the action call is complete.
Because the above two methods use a transport connection to send and receive messages, these methods are not suitable for long-running transactions. The reason is that the transport connection may timeout before the response is available. To resolve this issue, you can use two different connections to send the request and receive the response separately. However, because of the use of other transport connections to get the response, you need to associate the request with the response. AXIS2 supports ws-addressing, which resolves this issue by using the <wsa:MessageID> and <wsa:RelatesTo> headers. Therefore, if two transports are used, the module addressing is supported, as shown in the following two patterns.
Blocks Dual transport mode : This mode is useful when the service operation is essentially in-out, but the transport used is one-way (such as SMTP) or the service execution takes a long time and the HTTP connection times out. See listing 6 below.
listing 6. Block Dual transmission mode
try{ EndpointReference Targetepr = new EndpointReference ( "Http://localhost:8080/axis2/services/StockQuoteService");
Omfactory FAC = omabstractfactory.getomfactory (); Omnamespace omns = Fac.createomnamespace ( "Http://www.developerworks.com/example", "example"); Omelement payload = fac.createomelement ("GetQuote", omns); Payload.settext ("IBM");
Call call = new Call (); Call.setto (TARGETEPR);
Call.settransportinfo ( Constants.transport_http, Constants.transport_http, true);
Blocking invocation Omelement result = call.invokeblocking ("GetQuote", payload); System.out.println ("Quote =" +result.gettext ());
}catch (Axisfault axisfault) { Axisfault.printstacktrace (); }catch (Exception ex) { Ex.printstacktrace (); }
|
Non-blocking Dual Transport mode : This pattern provides maximum flexibility in terms of API-level and transport-level non-blocking, as shown in Listing 7 below.
Listing 7. Non-blocking dual transmission mode
try {
EndpointReference Targetepr = new EndpointReference ( "Http://localhost:8080/axis2/services/StockQuoteService"); Omfactory FAC = omabstractfactory.getomfactory (); Omnamespace omns = Fac.createomnamespace ( "Http://www.developerworks.com/example", "example"); Omelement payload = fac.createomelement ("GetQuote", omns); Payload.settext ("IBM");
Call call = new Call (); Call.setto (TARGETEPR);
Call.settransportinfo ( Constants.transport_http, Constants.transport_http, true); Callback to handle the response
Callback Callback = new Callback () { public void OnComplete (asyncresult result) { System.out.println ("Quote =" + Result.getresponseenvelope (). GetBody (). Getfirstelement () . GetText ()); }
public void ReportError (Exception e) { E.printstacktrace (); } };
non-blocking invocation
Call.invokenonblocking ("GetQuote", payload, callback); Wait till the callback receives the response.
while (!callback.iscomplete ()) { Thread.Sleep (1000); } Call.close (); }catch (Axisfault axisfault) { Axisfault.printstacktrace (); }catch (Exception ex) { Ex.printstacktrace (); }
|
|
Back to the top of the page |
|
Summarize
In part 1th of this two-part series, you learned about the AXIS2 architecture and how to deploy and use a simple Web service using different invocation patterns. In the 2nd part of this series, you will learn more about the architecture and how to customize Axis2 by adding handlers and AXIS2 message sinks. You will also learn how to use the XMLBeans data-binding support provided by AXIS2.