I am faced with a very tricky scenario, I have a web-service using SOAP 1.2 and I would like to gracefully handle the exception in case a message was sent with SOAP 1.1 header instead of 1.2.
Currently, my messageFactory implementation is SAAJ, and it throws a SoapMessageCreationException when I send 1.1 headers, and my code below does not work and does not catch the error properly:
#Bean
public SoapFaultMappingExceptionResolver exceptionResolver(){
SoapFaultMappingExceptionResolver exceptionResolver = new DetailSoapFaultDefinitionExceptionResolver();
SoapFaultDefinition faultDefinition = new SoapFaultDefinition();
faultDefinition.setFaultCode(SoapFaultDefinition.SERVER);
exceptionResolver.setDefaultFault(faultDefinition);
Properties errorMappings = new Properties();
errorMappings.setProperty(Exception.class.getName(), SoapFaultDefinition.SERVER.toString());
errorMappings.setProperty(ServiceFaultException.class.getName(), SoapFaultDefinition.SERVER.toString());
exceptionResolver.setExceptionMappings(errorMappings);
exceptionResolver.setOrder(1);
return exceptionResolver;
}
I took the example from https://memorynotfound.com/spring-ws-add-detail-soapfault-exception-handling/ however it does not seem to work in my case.
The only approach I have found that works is How to return custom SOAP Error from Spring Boot Endpoint Service? which to be is very much an overkill.
If anyone has come across this issue before, I would love some pointers!
Related
I'm using Spring WebFlux with functional endpoints to create an API. To provide the results I want, I need to consume an external RESTful API, and to do that in a async way I'm using a WebClient implementation. It works well and goes like this:
public WeatherWebClient() {
this.weatherWebClient = WebClient.create("http://api.openweathermap.org/data/2.5/weather");
}
public Mono<WeatherApiResponse> getWeatherByCityName(String cityName) {
return weatherWebClient
.get()
.uri(uriBuilder -> uriBuilder
.queryParam("q", cityName)
.queryParam("units", "metric")
.queryParam("appid", API_KEY)
.build())
.accept(APPLICATION_JSON)
.retrieve()
.bodyToMono(WeatherApiResponse.class);
}
As this performs network access, it's a good use case for NetFlix OSS Hystrix. I've tried using spring-cloud-starter-netflix-hystrix, adding #HystrixCommand to the method above, but there's no way to make it trip the circuit, even if I set a bad URL (404) or wrong API_KEY (401).
I thought this could be a problem of compatibility with the WebFlux itself, but setting property #HystrixProperty(name="circuitBreaker.forceOpen", value="true") indeed forces the fallback method to run.
Am I missing something? Is this approach incompatible with Spring WebClients?
Thanks!
#HystrixCommand won't really work, because Hystrix doesn't threat Mono/Flux any different from Java primitives.
Hystrix doesn't monitor content of Mono, but only the result of call public Mono<WeatherApiResponse> getWeatherByCityName(String cityName).
This result is always OK, because reactive-call-chain creation will always succeed.
What you need, is to make Hystrix threat Mono/Flux differently.
In Spring Cloud, there is a builder, to wrap Mono/Flux with HystrixCommand.
Mono<WeatherApiResponse> call = this.getWeatherByCityName(String cityName);
Mono<WeatherApiResponse> callWrappedWithHystrix = HystrixCommands
.from(call)
.fallback(Mono.just(WeatherApiResponse.EMPTY))
.commandName("getWeatherByCityName")
.toMono();
I have some strange problem with dropwizard exception handling. I wrote custom exception mapper very similar to this http://gary-rowe.com/agilestack/2012/10/23/how-to-implement-a-runtimeexceptionmapper-for-dropwizard/ . For status 400 my code is
if (webAppException.getResponse().getStatus() == 400) {
return Response
.status(Response.Status.BAD_REQUEST)
.entity("Request sent to server is bad.")
.build();
}
In code when i use throw new WebApplicationException(400) it works great, mapper catches exception and return response with a message but when i modify code to look like this
String msg=webAppException.getResponse().getEntity().toString();
return Response
.status(Response.Status.BAD_REQUEST)
.entity("Request sent to server is bad."+msg)
.build();
and in code use something like this
throw new WebApplicationException(Response.status(400).entity("hello!").build())
it returns just "hello!". Mapper does not catch this exception at all. It only catch when i provide just status code. I removed all dropwizard mappers using instructions from this link http://thoughtspark.org/2013/02/25/dropwizard-and-jersey-exceptionmappers/ but it still does not catch this exception. It is not because of above modification in mapper because it does not call "toResponse" method at all. So, my question is why it behave like this. I could leave like this it is "good enough", but i want to know why it wont work and it would be better if it works with mapper so i can handle exceptions easier.
Thanks in advance
By debugging we found that this behaviour is done in org.glassfish.jersey.server.ServerRuntime (mapException method).
This method checks if (throwable instanceof WebApplicationException) and then if (waeResponse.hasEntity()), and in that case it just returns the waeResponse without calling any exception mapper.
So, when you throw a WebApplicationException with a response that contains an entity, it won't reach your exception mapper.
I'm newbie for JUnit test case. Please help me on this issue. I have 2 mule flows- first flow having MQ as inbound and it has datamapper to transformer the xml. With the first flow input, i'm calling second flow where we are calling the existing service ( SOAP/HTTP) call. Please find my JUnit below. I'm able to get the success response. But my requirement
1. I need to see the transformer response coming out from the Transformer.( Like how we see via logger component in our flow)
2.Need to override the url (HTTP) through JUnit ( in order to test the error scenario)
public class Request_SuccessPath extends FunctionalTestCase {
#Test
public void BulkRequest () throws Exception {
MuleClient client = muleContext.getClient();
System.out.println("test");
String payload = " <root> <messageName>str1234</messageName><messageId>12345</messageId><DS>123</DS><</root>";
MuleMessage reply = client.send ("vm://test",payload ,null);}
#Override
protected String getConfigResources() {
// TODO Auto-generated method stub
return "src/main/app/project.xml";}
i thought the following snippet will override the url.But it is not
DefaultHttpClient client1 = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://localhost:7800/service);
assertNotNull(response);
3. How to take the control of the flow and see any response inbetween the flow.
Instead of WMQ, i have replaced VM as inbound end point for testing purposes.
4. Is there any chance like without replacing VM can we call directly with WMQ through JUnit TestCase. Kindly help me on this.
I'm using 3.4 version, not using maven as of now. Please help me. Thanks in advance.
1) What do you mean by "see". Would it work logging it? inspecting it while debugging?
2) You should parametrize your endpoint with a variable, something like
and configure a property placeholder as explained here: http://www.mulesoft.org/documentation/display/current/Using+Parameters+in+Your+Configuration+Files
Adding http.port, http.host and http.path variables to mule-app.properties
taking into account that you must set system-properties-mode="OVERRIDE" and then start your Mule server using bin/mule -M-Dhttp.host=your-host -M-Dhttp.port=your-port -M-Dhttp.path=your-path
3) Yes, WMQ has a Java API you can use to interact with it: http://publib.boulder.ibm.com/infocenter/wmqv6/v6r0/index.jsp?topic=%2Fcom.ibm.mq.csqzaw.doc%2Fuj41013_.htm , you will probably found hundreds of examples by googling about it.
Regards.
my application consists of 3 layers and is very straightforward.
class library with all the business logic
WCF service that exposes the class library
asp.net web UI.
At the class library layer, I have an enterprise library exception handling policy defined so that it logs all exceptions to the database. In the underlying code, exceptions are thrown, and they coalesce up to the facade. In the facade, I trigger the EL policy to log the errors, and then I toggle a sucessStatus boolean in the response and have a method to convert all my exceptions to a friendly list so that the ultimate consumer can dig through this to get any idea of whats going on.
My facade in my class library sort of looks like this:
public SomeResponse DoSomething(SomeRequest request)
{
SomeResponse response = new SomeResponse();
try
{
response.data = SomeOperationThatWillThrowAnException;
}
catch (InvalidOperationException ex)
{
var exceptionManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();
exceptionManager.HandleException(ex, "StandardPolicy");
response.Errors.Add(Utility.ExceptionToError(ex));
response.SuccessStatus = false;
}
return response;
}
If I build a simple winform client and have it talk to my class library, this works.
However when I use the full stack, I get "fault exception was unhandled by user code". I can't seem to configure EL at the WCF layer in any way to keep this from happening.
My WCF service is just a simple wrapper for my class library facade.
public SomeResponse DoSomething(SomeRequest request)
{
return new MyFacade.DoSomething(request);
}
What I want is to have the class library handle the error silently, and not trigger any exceptions at the WCF or UI level. I want the consumer (in this case the ASP.NET webform UI) to have to check the response message contents to get a clue of what happened instead of having an exception stop execution dead in its tracks.
You likely have an error in your configuration file resulting in GetInstance() or HandleException() throwing an exception. Have you tried debugging the WCF service?
We are developing a proxy in WCF that will serve as a means of communication for some handhelds running our custom client application. I am curious what error handling strategies people use as I would rather not wrap EVERY proxy call in try/catch.
When I develop ASP .NET I dont catch the majority of exceptions, I leverage Application_Error in Global asax which can then log the exception, send an email, and redirect the user to a custom error landing page. What I am looking for in WCF is similar to this, except that it would allow me to pass a general faultreason to the client from a central location.
Basically I am curious how people centralize their exception handling in WCF apps.
Thanks
You might find the IErrorHandler interface useful here. We've been using this to do pretty much what you mention - centralised exception logging and providing generalised fault reasons without having to litter the code with numerous try/catches to try and deal with the problem locally.
So here is what I did. We have a few custom exceptions in our application such as BusinessRuleException and ProcessException, WCF supports both FaultException and FaultException<T>.
General practice seems to be that you always throw FaultException to the client in the case of a general error or an error that you dont want to display exactly what happened. In other cases you can pass FaultException<T> where T is a class with information about the particular exception.
I created this concept of Violations in the application, which basically meant that any custom exception had a property containing the corresponding Violation instance. This instance was then passed down to the client enabling the client to recognize when a recoverable error had occured.
This solved part of the problem, but I still wanted a general catch all that would allow me to centeralize logging. I found this by using the IErrorHandle interface and adding my own custom error handler to WCF. Here is the code:
public class ServiceHostGeneralErrorHandler : IErrorHandler
{
public void ProvideFault(Exception ex, MessageVersion version, ref Message fault)
{
if (ex is FaultException)
return;
// a general message to the client
var faultException = new FaultException("A General Error Occured");
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, null);
}
public bool HandleError(Exception ex)
{
// log the exception
// mark as handled
return true;
}
}
Using this method, I can convert the exception from whatever it is to something that can be easily displayed on the client while at the same time logging the real exception for the IT staff to see. So far this approach is working quite well and follows the same structure as other modules in the application.
We use the Exception Handling Application block and shield most faults from clients to avoid disclosing sensitive information, this article might be a good starting point for you, as with "best practices" - you should use what fits your domain.