How to write Spring Interceptor to handle any Web Service exception - web-services

I am working on a Web Project which is having few SOAP Web Services that we are developing using CXF 2.7.8(& Spring 3.0.7). I have a requirement to add interceptor which can handle the exception occurred during a method call, extract the root cause and send it to the caller.
We don't have any Controllers in our web project as we don't have UI. The project is hosting few web services only.
I implemented a Spring based interceptor by referring to the sample code/example available on internet. By my interceptor is not being called when I call a webservice method. The same code/interceptor works fine in different web application which has a Controller (and uses Spring MVC flow).
I am not sure why it is not working? Is it because that we don't have Spring MVC based flow and I am trying to use a Spring Interceptor? If yes, then could somebody please suggest as how can I write an interceptor which will be called when some exception occurs. I am using CXF based SOAP web services.
Below is the Interceptor & Spring configuration that I tried:
public class ExceptionHandlerInterceptor extends HandlerInterceptorAdapter {
private static final Logger LOG = Logger
.getLogger(ExceptionHandlerInterceptor.class);
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
LOG.info("Before handling the request");
return super.preHandle(request, response, handler);
}
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
LOG.info("After handling the request");
super.postHandle(request, response, handler, modelAndView);
}
// #SuppressWarnings({ "unchecked", "rawtypes" })
#Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
LOG.info("After rendering the view");
System.out.println("Exception is-->" + ex);
super.afterCompletion(request, response, handler, ex);
}
}
And this is the Spring configuration:

Related

Cxf interceptors for http exceptions

We are using jaws:client to consume a web service. We have inFaultInterceptor that captures soap faults for further processing. But this inFaultInterceptor is not being invoked for http errors like 404 or ConnectException. We configured interceptors to jaws:client. Can we write any interceptor that captures these http exceptions? Is there any better way to capture them? All we want is to take the control back when such exception/error occurrs.
Note: we cannot catch them in web service code due to some restrictions.
You can use a FaultListener added to CXF Bus. The listener will capture the http exceptions allowing you to execute your code before they are raised to invoking method.
ClientProxy.getClient(jaxWSClientProxy).getBus().getProperties().put("org.apache.cxf.logging.FaultListener",new CxfFaultListenerImpl());
public class CxfFaultListenerImpl implements FaultListener{
public boolean faultOccurred(final Exception exception,final String description,final Message message) {
//return false to avoid standard CXF logging of exception
return false;
}
}

Apache CXF web service response re-routing on web service client gone detection

Working with Apache Camel for EIP, I have an Apache CXF Web Service Endpoint which when called, will put requests into an MQ queue. Requests in that MQ queue are processed asynchronously where, responses are then generated and placed into a response MQ queue. The Apache CXF Web Service collects a request's response from the response MQ queue which it then writes to the Exchange's out channel for the calling client to receive.
Is it possible to configure my web service so that it can detect if a client is still connected when it is trying to send the asynchronous response back to it? And when this detect occurs, to route the response to another Camel route?
A use case scenario would be for example where the client makes a call to the web service but disconnects after 5 seconds of not receiving a response from the web service. And later, when the web service processes the request and fails to send the response to the no longer connected client, it re-routes the response to, for example, an smtp route.
* UPDATE *
Having read various online documentation and forum posts, I have my service configured as follows:
<camelContext xmlns="http://camel.apache.org/schema/spring" handleFault="true">
<routeBuilder ref="aServiceRoute" />
</camelContext>
and in my AServiceRoute route, I have configured my route as follows:
#Override
public void configure() throws Exception {
onException(Exception.class).process(new Processor() {
public void process(Exchange exchange) throws Exception {
log.debug("caught Exception A!!!");
}});
from(cxfUri)
.onException(Exception.class).process(new Processor() {
public void process(Exchange exchange) throws Exception {
log.debug("caught Exception B!!!");
}}).end()
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
// do something..
}
})
.to(ExchangePattern.InOut, mqUri);
For my first test, I force an Exception throw in the process where the // do something.. comment is. When I run this test, I see the log "caught Exception A!!!" which is great.
For my second test, I basically run the test scenario I have described in this post. When I run this test, I see a cxf stacktrace logged:
=09-05-14 12:25:32 [WARN ] org.apache.cxf.phase.PhaseInterceptorChain - Interceptor for {http://camel.apache.org/cxf/jaxws/provider}DefaultPayloadProviderSEIService#{http://cxf.component.camel.apache.org/}invoke has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Could not send Message.
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:64)
but none of my route's onException() methods are called.
What am I missing? Do I need to place the onException() method somewhere else in service's route?
Thanks in advance, PM.
The Dead Letter Channel will offer the behaviour you need: https://camel.apache.org/dead-letter-channel.html

JavaFX2: Consume Restful services

I am trying to work on an architecture to consume RESTFul services from a JavaFX application. The requirement is to use spring's rest template(Not too pressed for this. If spring does not work then probably I can look at jersey or resteasy.
My setup is as below:
My main class has a dropdown listing values from a RESTFul service.
The architecture to hit the RESTFul services is as below:
I have a client class that gives me the instance of the service class that hits the rest services.
In the service class, I have various methods that I hit on the RESTFul service.
public MyService1()
{
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MyConfig.class);
context.registerShutdownHook();
}
#Autowired
private RestOperations restTemplate;
private final Logger LOG = LoggerFactory.getLogger(MyService1.class);
public List<MyObject> getMyObjects() throws IOException
{
HttpEntity<MultiValueMap<String, HttpEntity<?>>> request = new HttpEntity<MultiValueMap<String, HttpEntity<?>>>(
createParts(), createMultiPartHeaders());
Map<String, String> vars = new HashMap<String, String>();
List<MyObject> myObjects = restTemplate.getForObject(
"http://localhost:8080/my-webservices/objects", List.class, vars);
return myObjects;
}
With the above setup, I get the exception:
Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:403)
at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:47)
at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:115)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.beans.factory.BeanCreationException
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:581)
It seems like you have not added the dependency library containing "BeanCreationException" class. Please add the jar file of spring as dependency for that JavaFX Project.

Scope 'session' is not active for the current thread

I have two Spring applications: client and server. On server application are services, on client app is view logic. Both apps should communicate through web-services, but this did not work because of error
Request processing failed; nested exception is
org.springframework.remoting.jaxws.JaxWsSoapFaultException: Error
creating bean with name 'scopedTarget.jcrSession': Scope 'session' is
not active for the current thread; consider defining a scoped proxy
for this bean if you intend to refer to it from a singleton; nested
exception is java.lang.IllegalStateException: No thread-bound request
found: Are you referring to request attributes outside of an actual
web request, or processing a request outside of the originally
receiving thread? If you are actually operating within a web request
and still receive this message, your code is probably running outside
of DispatcherServlet/DispatcherPortlet: In this case, use
RequestContextListener or RequestContextFilter to expose the current
request.
On server app i'm using JCR Session (session scoped bean)
<bean name="jcrSession" factory-bean="sessionFactory" factory-method="login" scope="session" destroy-method="logout" >
<aop:scoped-proxy/>
</bean>
in web.xml of server app I have
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
When I access WSDL files produced by server app in browser, everything is OK. When I use server app services locally (e.g. in controller on server app) everything is also OK. So why this error occurs, when I try to access services through web-services from remote app?
Update1
jcrSession is crated by SessionFactory class. Then this jcrSession is autowired to DAO objects using springs #Autowired.
Example of simplified `JcrSessionFactory`:
public class JcrSessionFactory {
private Repository repository;
private Credentials credentials;
private Session session;
public Session login() {
session = repository.login(credentials);
return session;
}
public void logout() {
session.logout();
}
}
Also, same error occured when I tried to autowire service in same app and use it in method annotated by #PostConstruct or in implementation of InitializingBean in method afterPropertiesSet()

Writing Webservice clients using HttpURLConnection

I have a question related to Axis2 Webservices .
I have My Webservice deployed in Tomcat Server .
Right now i am writing a Client for my Webservice using
public static void main(String[] args) {
try {
samples.quickstart.StockQuoteServiceStub stub = new samples.quickstart.StockQuoteServiceStub();
samples.quickstart.StockQuoteServiceStub.GetPrice request = new samples.quickstart.StockQuoteServiceStub.GetPrice();
request.setSymbol("ABCDE");
samples.quickstart.StockQuoteServiceStub.GetPriceResponse response = stub
.getPrice(request);
}
catch (org.apache.axis2.AxisFault e) {
e.printStackTrace();
} catch (java.rmi.RemoteException e) {
e.printStackTrace();
}
}
This works fine.
I have seen from net some clients are written using HttpURLConnection.
Please tell me what is the difference between writing clients by using the former way and the later way.
The way you have done give you a more abstract way. It has generated the code for you and you need only to provide the parameters to pass. Here Axis2 users the commons httpclient as to send message using http transport. As you can see Axis2 handles all the transport specific things for you.
On the other hand you can create the soap message to send from your own and send using an httpClient. But there you need to do a lot of work.