A Web service is obviously an application deployed in a Web service engine. Service implementation, service descriptors, and the way of deploying them vary one engine to another. No matter what Web service engine you are using, there are two main approaches to writing a Web service:
The recommended way to write a service is to start from a WSDL file, but the code first approach is still valid; most developers use that technique for their application. One of the concerns with the contract first approach is writing the WSDL document to match his requirement; that obviously requires a good knowledge of WSDL.
If you are new to the world of Web services, your knowledge of WSDL may not enough to write your own WSDL file and then create the service using the WSDL document. So, the best way is to start from a Java class and learn how to expose the Java class as a Web service.
At runtime, no one can understand whether the service was created using code first approach or contract first approach because what you have at the runtime is a set of Java classes. There are three main steps involve in creating a new Web service using the code first approach in Axis2:
There is no magic involved or no special things to remember when writing a service implementation class. If you are trying to use Axis2's advanced features such as session management and service life cycle, of course you have to do few additional things. But, for a simple Web service, it is very straightforward to write the service implementation class. The following code snippet demonstrates what the service implementation class for the "hello" Web service looks like.
public class HelloWorld { public String sayHello(String name) { return "Hello " + name; } }
This simple Java class has one public method. It takes a string name as an argument and returns a string value as the result.
To be a valid service in Axis2 when deploying as an archive file, you have to have services.xml inside the service archive file. services.xml is nothing but the deployment descriptor for the service that you are trying to deploy. The service deployment descriptor will tell the deployment module how to configure and deploy the service. Writing a services.xml for service mentioned above is very simple and very straightforward. There are few things you have to remember when writing such a services.xml file:
Note: Axis2 has a set of built-in message receivers; some of them can only handle a XML-in, XML-out scenario; those are called RawXML message receivers. Meanwhile, there are message receivers that can handle any kind of JavaBeans + simple Java types + XML; those are called RPC message receivers. According to the sample code above, it is obvious that you can use none of the RawXML message receivers for this particular service, so the simple answer is to use RPC message receivers.
There are different ways to write services.xml; they vary depending on the way you specify the message receivers, operation overriding, and so forth. You should start with very basic services.xml to understand the concept very easily, so the services.xml corresponding to the service above can be written as follows:
This is my first service, which says hello HelloWorld
I have bolded few lines in services.xml above; those are the important XML tags that you have to remember when writing a services.xml.
To specify the corresponding service implementation class, you need to add a parameter with the name ServiceClass; the value of that parameter should be the fully qualified name of the service implementation class.
There are a few ways to specify the message receiver for a given service. One way is to add the operation tag with the actual Java method name and include the message receiver inside the operation tag. The services.xml mentioned above has followed this approach. As you can see, the service implementation class has a method called sayHello, and services.xml has an operation tag with the same name. Inside the operation element ,it has added the message receiver element.
The next step is to create a service archive file by putting the compile codes of the service implementation class and services.xml. The inside folder structure of the service archive file will look like the following:
HelloWorld.aar META-INF Services.xml HelloWorld.class
Deploying the service is just a matter of dropping the service archive file into the services directory in your aixs2 server repository. If your server is Tomcat, you easily can upload the service by using axis2 Web administration console.
Note: In this case, the name of the deployed service will be HelloWorld.
As mentioned above, there are a few ways to specify message receivers for a given service:
The example described above has used the first approach, where it has specified the message receiver at the operation level.
Think about the scenario where you have a large number of operations to be published in services.xml; in this case, adding a message receiver for each and every operation seems useless. If you can specify a message receiver for whole service, it makes the service author's job easier and simplifies services.xml as well.
Axis2 has built-in support for all the eight MEPs (Message Exchange Pattern) defined in WSDL 2.0. In services.xml, you can specify the MEP and corresponding message receiver, and then, depending on who the MEP operation belongs to, axis2 automatically picks up the message receiver and sets the selected message receiver to the operation.
Note: Inside the operation tag in services.xml, you can add an attribute to specify the MEP of the operation as follows:
Defining the service level message receivers for a given service is as shown below:
According to services.xml, RPCMessageReceiver is the message receiver for all the in-out operations (for any operation that belongs to in-out, MEP will assign this message receiver as its message receiver) in the service; in the meantime, the service level message receiver for in-only MEP is RPCInOnlyMessageReceiver. If you redeploy the HelloWorld service with a new services.xml, you will definitely get the same result if you invoke the service again.
There may be instances where the service author wants to use different message receiver for one or two operations while he has defined service level message receivers. To override service level message receiver by operation can be easily achieved by just adding message receiver element to the operation that you want to override. A sample services.xml which follows this technique is shown below.
Operation sayHello uses a different message receiver than its service level message receivers.
Note: All the public methods in the service implementation class are exposed whether you specified that in services.xml or not. Axis2 calculates the MEP of an operation by checking its corresponding java method. If the method is void, the MEP will be in-only; else, it will be in-out, depending on which MEP message receiver will be set.
Accessing Message context inside the service implementation class
Message context is the property bag + the incoming SOAP message representation in Axis2. There are some services that want to access message context inside its service implementation class; one probable use case could be to access a transport header inside the service and make a decision on that. Axis2 uses a technique called dependency injection to inject message context to the service implementation class; Axis2 uses Java reflection for that. So, if the service wants to access message context inside its service implementation class, it has to add a method called setOperationContext to service the implementation class as follows.
public class HelloWorld { private MessageContext inMesasgeContext; public void setOperationContext(OperationContext opCtx) throws AxisFault { inMesasgeContext = opCtx.getMessageContext( WSDLConstants.MESSAGE_LABEL_IN_VALUE); } public String sayHello(String name) { return "Hello " + name; } }Note: Axis2 calls setOperationContext using Hava reflection before it calls an actual Java method corresponding to the incoming message.Service group and single service
To deploy multiple services (they may be logically related or not) together in a single service archive file, Axis2 introduced the concept of a service group. There, you can have multiple service implementation classes and only one services.xml file to describe all the services. The only difference here is that root element of services.xml is changed to serviceGroup instead of service. As an example, say you want to deploy two services together in a single service archive file and further assume that names of them are MyService1 and MyService2 respectively. The services.xml file can be written as follows:
........................ ....................... The only difference in the service element compared to HelloWorld's services.xml is that here the service element has an additional attribute called name. If you want to have multiple service elements in the services.xml file, you must have the name attribute in each and every service element.
Contract first approach: Starting from WSDL
The easiest way to create a service is to start from WSDL; that is what happens in most production environments. When it comes to production, they have business scenarios and corresponding business contracts or the WSDL file, so why not start from there? The interesting thing is that once they have the WSDL file, both client and producer (service) are given the WSDL and they have to act according to that.
Axis2 has built-in support of the generation service code once you have the WSDL. In this case, as a service author, you have only to do the following few steps:
- Generate service code (service skeleton)
- Fill the service skeleton according to the business agreement
- Run the generated Ant build file
- Deploy the Ant-created service archive file into your application server where Axis2 is running
Generating code
Axis2 came with a set of tools and IDE plug-ins for code generation (WSDL2Code) to make the work easier. So, you can choose any kind of code generation tool to generate a service skeleton. In the meantime, there is a set of databinding framework support; you can select one of them as your databinding. As an example, you can select xmlbeans, adb, or any other available databinding framework (jibx, jaxme, and so forth). Once you generate server side code, it generates:
- Service skeleton class
- Message receivers (most of the time, one or two)
- services.xml
- services.wsdl
- Ant build file
Filling the service skeleton
Axis2 generates a service skeleton class to throw UnSupportOperation from each method. You have to implement the service skeleton class as you want.
Running ant build file
After completing the service skeleton, the next step is to create a service archive file using generated code. To make the job simple, Axis2 generates an Ant build file to create service archive file for you; you have to open the command line console, go to the folder where you generated code, and then type ant build there in the console to run the ant build file. Then, it creates the service archive file for you.
Summary
Making a Java class into a Web service is very straightforward in Axis2. Once you know how to write services.xml correctly, deploying a service is just a matter of creating a service archive file and dropping it into the services directory in the repository. WSDL's first approach is the easiest way to creating a service because Axis2 has built-in support for code generation and a set of tools to make the job easier.
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。