How to handle Exceptions in Apache CXF - web-services

I'm using the CXF for developing webservices.
But I was wondering what is Best Practice for handling exceptions? Let's say I have a webservice-operation, create(User user).
The incoming user is an instance of my User domain class, and can be saved directly by the UI Team by calling user.save()
If the save() for some reason fail (e.g. some Network connectivity fail , or some data validation error from User DTO ), how would Best Practice dictate that I serve this exception to the client?
I mean: Which type of Exception would be suitable?
Should this Exception be included in the operations signature ??
public Response createUser(User user);
#WebService
public interface EmpService {
public Response createUser(User user);
}
And how should the client-side handle this exception?

One company I was working in, with web services had almost 15 years of experience, so I have learned some things. We handled the exception simply by specified throws statement in the method. And if some expected error occurred, we just simply constructed the exception and throw it with the message which pointing to reason why something has failed.
The client should handle all exceptions thrown by service in anyway he likes to do it. If you are developing a web service, you need to be worried about how to correctly create an exception with appropriate reason in it. And when exception occurs the client will see it anyway.

Related

Customize endpoint mapping in spring-ws

I'm implementing a SOAP web service using Spring WS.
Most of my implementation is done using types with #Endpoint annotations and methods in these types with #SoapAction annotations. Some endpoint interceptors also help glue things together.
I'm using Spring exception handling with SoapFaultAnnotationExceptionResolver that enriches the SoapFault with some specific details.
This works very well. But I have a customer requirement that says that I also have to provide customized SoapFaults for those cases where the service is invoked with an invalid soap-action. Meaning, a soap action for which I have no matching #SoapAction annotation.
What happens now is that Spring logs this:
[WARN] org.springframework.ws.server.EndpointNotFound No endpoint mapping found for [AxiomSoapMessage {http://www.example.com/myservice/xml.schema/2010/06/01}MyRequest]
I get this returned along with a 404 return code from the Jetty server that hosts this web service.
How can I catch these exceptions and add some custom soapfault handling in this situation? It seems like if only org.springframework.ws.NoEndpointFoundException had a #SoapFault annotation, I could have it go through my exception resolver and customize it that way. But it doesn't, unfortunately.
I think I may have to implement some custom "catch-all" endpoint mapping but I'm just not sure how to do this, and how to ensure that mapping to the specific endpoints are attempted first.
Anyone have a suggestion for how to do this?
The exception seems to be thrown from the class MessageDispatcher in the method dispatch:
mappedEndpoint = getEndpoint(messageContext);
if (mappedEndpoint == null || mappedEndpoint.getEndpoint() == null) {
throw new NoEndpointFoundException(messageContext.getRequest());
I suggest to extends this class and instead of throwing an exception, you could add a soap fault as such:
SoapMessage response = (SoapMessage) messageContext.getResponse();
String faultString = "any message"
SoapBody body = response.getSoapBody();
SoapFault fault = body.addServerOrReceiverFault(faultString, getLocale());
You can take a look SimpleSoapExceptionResolver that deals with exceptions on the endpoints.

Return a soap fault from spring ws

I'm looking for some way to respond to a SOAP request with a soap fault.
Right now I can only create a fault when an exception is thrown via an AbstractEndpointExceptionResolver.
I have looked at an EndpointInterceptorAdapter but I'm not sure how to inspect or modify the response. For instance if an endpoint returns a ValidResponse but there were no values found or returned in a list in the response I would like to respond to the users request with a SoapFault instead.
We make efforts to follow "Don't Use Exceptions For Flow Control" but I've been un-successful with creating a SoapFault from an interceptor or from the endpoint without throwing an exception.
Well, I think AbstractValidatingInterceptor comes to the rescue. At least from source code part: how to handle response from interceptor and how to deal with WebServiceMessage response.
Bear in mind, the WebServiceMessage can be cast to the SoapMessage and you can populate your custom SoapFault using its SoapBody:
SoapBody soapBody = ((SoapMessage) messageContext.getResponse()).getSoapBody();

How to use Intersystem's session within web services

I am trying to set some session information in one web method and return it in another web method, but the session data is always empty on the second web method. Here is what I tried
Web Method 1 - Sets session information
Method StartSession() As %String [WebMethod]
{
set %session.NewSession = 1
set %session.Data("key") = "dude"
Quit "Session Started"
}
Web Method 2 - Gets session information should return dude, but is returning blank
Method TestSession() As %String [WebMethod]
{
Quit $Get(%session.Data("key"))
}
To use sessions with Cache web services you need to set the SOAPSESSION class parameter of your web service class equal to 1.
Doing so will cause the web service to return a SOAP session header in the response. If you are using a client that was built to expect this header you may not need to set up anything else. Otherwise, your client application will have to read this header and include it in all further requests, so the server can know which session you are using. An example of this header given in the documentation is:
<csp:CSPCHD xmlns:csp="http://www.intersystems.com/SOAPheaders">value of
CPSCHD token</csp:CSPCHD>
Note that security is a separate issue that your example doesn't address.
Also note that Intersystems has decided that web services will continue to use a license for some period of time after the call has been made. I can't find documentation on this, and I believe it's something like a few seconds per call. I believe that this can cause license issues that would not occur if you used other software to provide web services, and had that other software call Cache via some mechanism other than web services. I believe this is true even when that other software carefully follows all the rules in the license agreement about named and anonymous users. However, I'm not certain about any of this licensing stuff. Still, you might want to do some testing before you commit to an architecture.
As an alternative to psr's answer another way to handle state is to use custom SOAP headers.
For example:
Create a class for your custom SOAP headers like below:
Class Headers.TimeStamp Extends %SOAP.Header
{
Property TimeSent As %TimeStamp;
}
In the web method do this:
set h=##class(Headers.TimeStamp).%New()
set h.TimeSent=$ZTIMESTAMP
do ..HeadersOut.SetAt(h,"Timestamp")
This will generate the following SOAP header:
<SOAP-ENV:Header>
<TimeStamp xmlns:hdr="http://www.myapp.org">
<TimeSent>60712,70996.027Z</TimeSent>
</TimeStamp>
</SOAP-ENV:Header>
This will allow state to be maintained within the SOAP headers rather than using Cache's session management.

Is it proper to use HTTP response code representing business exception on server side?

The background is like this:
The client web browser send a request to the server;
The server program will launch some biz check rules before doing the real work.
If check fail, some tips should be feed back to the client browser.
So, here is the question. Should I use an error response http code to indicate this, or use 200 directly, and then parse the message from response body.
Sometimes, this is not a problem. But, some client component give some util methods if error code returned. So, that's a hard decision to make:
return 200,and error message. parse and show them myself;
return some code like 500, let the client component to show it directly.
I would suggest to use as many http status codes as possible. That is a standard and why should you not use them?
Here are some examples where IMHO the usage of http status codes makes sense:
Somebody wants a dataset wich is not aviable use 404 not found
A secured ressource needs an authentification use 401
A ressource which is not aviable for the currient user should get a 403 forbidden
A error accours which you cannot handle well write out an 500 status
And so on
Look also for the logic for REST-APIs there you can see the advantages.
Typically, you'll want to indicate the reason the service failed. Returning custom errors can also potentially allow the client application to respond in an appropriate way. If an input validation check fails, for instance, I imagine the user would appreciate the chance to fix and resubmit the request. An HTTP error won't be enough to indicate what exactly went wrong.

How to get/debug request message when calling a Web Service

I have an application that calls a Https web service (as it seems created with java, not sure though). I get an error as response:
"Error on verifying message against security policy Error code:1000"
Now I don't exactly understand the error code and currently cannot find any responsible to answer me correctly. I don't ask for the error ofcourse cause this could be something about certificates, security from server etc.
Though I would like to catch the request client call I make, and see the whole envelope message to compare with a couple of samples I have so I might catch something.
How can I do this....I remember there is a tool that u can do such things when debugging a WCF service call, can this tool be used in this situation? Can someone rember me the name of the tool :)
I created the client using Add Service Reference, from VS 2010 and it created some custom bindings. On these bindings it created this a tag with an attribute decompressionEnabled="true" but I deleted because VS was complaining attribute is not allowed!!!
The documentation I have for these services says about authentication credential inside the message transport object that serialized in the request (requestObject) but refers to another couple of password and username properties I cannot seem to find them. Tried to add the in client.ClientCredentials.UserName.UserName and Password properties, but I get a read only error there (strange not always).
They also mention in the specifications about Connect with SOAP Security Extensions (WS-Security) which I don't understand if me, the client, has to do something from it's side, aren't these supposed to extract in the config file when generated?
Any hints and tips are welcome.
Thank you.