Hello everybody and welcome to a new round of exploring.
The Christmas holidays (if you are celebrating) are just over so I thought it would be a good idea to talk about something that has also been around for a long time: web services. Obviously, they haven’t been around as long as Christmas but I bet that you have to spend some time trying to remember when you first used web services.
So, before we dive into the serious stuff, let’s check some interesting web services trivia:
- The standardization of the web services started in 2002 by W3C.
- The 3 major concepts from the initial specification are WSDL (Web Services Description Language), SOAP (Simple Object Access Protocol) and UDDI (Universal Description, Discovery, and Integration).
- Remember UDDI? Don’t worry. Very few do. Especially the “Discovery” part.
- An ancestor of the web services (in the Java world) is the RMI (Remote Method Invocation).
- Remember RMI? If you are in your 20s probably not.
But let’s conclude our trip down the memory lane before we get too emotional reminiscing about the good old days.
In the meantime (i.e the last 15 years) web services got a lot of traction and were adopted by the majority of the programming languages. It is now easy to create web service providers in one language and consume them in an application written in another language. Web services are not biased to a certain language or family of languages or language types (statically vs. dynamically typed).
Now as easy it is to work with web services in Java, for example, it is super easy to work with them in Integration Server(IS).
Assuming that you already have the services that you want to expose as web services, it takes somewhere around 20-30 seconds (depending on how fast you click and what options you want to be changed) to have a fully functional web service endpoint deployed on your IS. The same remark is valid for creating Web Service Consumers (WSC) out of the provider WSDL.
But you might say, where is the exploring part? Or are you writing this post just to preach how easy it is to work with web services in IS?
Well, before we go to the good stuff, let me just say it once again: It is super easy to work with web services in IS. Sure there will be some corner or more exceptional cases where you will need to do more than just click “Next” through some screens, but for the majority of the use cases, the defaults will suit you just fine.
By now you are thinking: “This guy wants to put everything in context..or what?”. I am getting there…now.
Did you ever think: “I would really like to see the SOAP message that I get before it is passed to the top level service and IS does its magic…” or “I wish I could ask the client application to sent me also some metadata regarding the message”.
Well, search no more because your responses lie in this 2 “H”: Headers and Handlers.
Let’s start with the first ”H”: Headers. To be more specific SOAP Headers.
The header(s) is an optional part of every SOAP message.
A SOAP message is composed of a so-called SOAP Envelope which in turn contains:
- SOAP Header (0..*)
- SOAP Body (1)
The SOAP Body contains the actual message payload or a SOAP Fault element in case an error occurred on the caller side.
The structure of the SOAP Fault (yes, this too has a structure) is not important for our talk, but you can find it here.
As explained above the SOAP Header and the SOAP Fault are optional. The next picture offers a visual representation of the SOAP message.
You might say now, OK, all fine and dandy in theory, by why use headers? Why not just send everything in the SOAP Body?
Well, the primary use of headers is to specify additional application-level requirements. SOAP Headers transport information that is not directly related to the particular message.
Things that can and should be transported in headers are:
- Authentication information
- Service consumer details (callee application, stage, version)
- Message details/metadata (type of message, messageId, correlationId): this is especially useful for problem tracing
- User details (assuming that the call was made from a web app context)
The usage rules here should be:
- Don’t transport the data from the header in the actual message because it will pervert the meaning of the message and of the service.
- Don’t transport the data from the message in the header. If the data is vital to the processing of the message then it should stay in the message.
A good resource for the header information and classification is this one. Go ahead and check it out. Now or after you have read my post. If you go now, don’t forget to come back. The webMethods stuff is right around the corner.
Now, there are a lot of cool stuff regarding headers that might be interesting, like the mustUnderstand attribute or the difference between SOAP and HTTP headers, but if I start talking about them this post will explode in size before getting the webMethods part of it.
So how do I add headers to my Integration Server Web Service Provider(WSP)? Well, it depends as there are 2 approaches to WSP creation: Code First and Contract First.
I will cover the Code First approach in this post and the Contract First in the next one. So stay tuned.
Code First approach to Web Services
This approach is the easiest one. Assuming that you already have the services (the code) that contain your logic, then you create the WSP based on the services.
After the WSP is created you can easily modify its properties and structure (you can add header documents, fault document, etc.)
Pausing the post for some administrative information:
- You can download the IS package used for the tutorial in the Download area at the end of this post.
- Click on the images to make them open full size in a popup window for a better viewing experience.
So let’s take it step by step.
I will start with a service that gets as input a PersonalInformation document type and for output has a greeting.
Next step is to create the WSP. Like I said, 20 seconds, on the clock.
Now let’s define a header structure. I want to have the following structure for the request header:
- messageId: to easily trace the message in my logs
- application: i.e the application that calls my web service
- user: the logged-in user of the callee application
I also want to have a response header that I attach to the response of the service. This one I want to have just:
- correlationId: which will actually be the messageId from the request header
This is just a minimal example of course. Your needs will dictate the content of the header.
Going further, you have to add the header document type in the Header section of the WSP (request header on the request, response header on the response).
You either drag and drop the document types in the Header section or use the special button for this purpose as can be seen in the below image.
That’s pretty much it. Go ahead and generate a client for your WSP with soapUI for example and you will see that the header is generated for the request.
At this point, although the header is there, it is not processed. This part will be explained in the Handlers section.
Important Note: For this tutorial, I did not let security interfere with the code 🙂 . Therefore when you generate the client and make the call use the IS Administrator credentials to make a successful call. Another option is to set the ACL on the WSP to “Anonymous”.
Even More Important Note: Security is a very important aspect of service development and should not be treated lightly or joked about. I have chosen to do this only for this didactic purpose. In your productive code go ahead and define an ACL or employ any other security mechanism, as you prefer.
Until this point, we covered the Headers part. Now we know and have defined the structure of the header documents and have added these documents as part of the SOAP header. Moreover, a client like soapUI can see this changes and generate the client accordingly.
What we need now is something that acts upon these headers. This “something” is called a Handler.
The usage of handlers is more or less the same for both types of web services: Contract First and Code First.
A more in-depth look at handlers can be found in chapter 6 of the “Web Services Developers Guide”. For now, it is sufficient to know that there are 3 types of handlers:
- Request handler: used with SOAP requests
- Response handler: used with SOAP responses
- Fault handler: used when the request handler fails
In the next part I will be talking about request and response handlers for WSP, but know that they can be added as well for WSC.
To create a handler you have to follow the steps below:
Create a handler service
This is an IS service with the following specification pub.handler.soap:handlerSpec. This specification defines the service signature.
I have created 2 handlers:
Code the handler service
In the handler service put the header processing code that you desire. You might want to take the header and validate it or just log some/all of it. It is really your call here.
What I did in the request handler service for this example is to:
- retrieve the service pipeline
- extract the header
- strip the namespace of the header
- make the header document available to the subsequent services (i.e the top level service and the response handler service)
For the response handler service, the flow is similar:
- retrieve the service pipeline
- extract the header document from the pipeline
- map the messageId of the request header to the correlationId of the response header
- add the response header to the message
Beware of the catch
If you are browsing through my code you might say: “Wait for a second! I see some wrapper documents for the headers. What are they and why didn’t you mention them until now?”.
I did not say anything until now because now is the moment, and the moment is now. (really deep this last sentence 🙂 ).
If you downloaded the code you might have seen 2 extra document types: com.explorer.wm.code.first.doc:RequestHeader and com.explorer.wm.code.first.doc:ResponseHeader.
If will explain shortly what they are used for. But first go ahead and check the WSDL section of the WSP. You will see there that the header documents have a namespace. For Code First WSPs it is usually the path to the header document (in our case: com.explorer.wm.code.first.doc).
To be able to extract the header from the request using the utility services that IS provides it is NOT sufficient to use the document type that was set in the header. We need a wrapper document type in order to be able to set the namespace of the header document.
I hope the next pictures will make things more clear. The remark is valid for both request and response handlers.
Register the handler
Using the service pub.soap.handler:registerWmProvider (pub.soap.handler:registerWmConsumer for consumers) you can tie together the handler services for the request, response and fault along with a descriptive name for the handler.
Important Note: This registration does not survive a server restart so make sure that you have a startup service that registers the handler (if it does not exist).
Assign the handler to the WSP
If you did the previous step correctly, you will be able to see the descriptive name of the handler. Add it to your WSP in the “Handlers” section like below.
Fire everything up and watch it run smoothly
And here we are at the end of a fairly long post. You can find attached the resources from the screenshots.
Feel free to use the provided code and/or modify it. Just note that it was developed on webMethods 9.8.
Until next time, I wish you Happy Holidays and a Happy New Year full of joy and exploration. 🙂
PS: Don’t miss my next post. We will be talking about the Contract First approach to Web Services, of course, with special attention to headers and handlers.
PPS: The next post will contain also all the things I might have forgotten to mention here 🙂 .