I am using open feign to communicate between 2 microservices.The micro service to which feign client communicate throws a custom exception for incorrect post request parameters sent through feign client.
When a http bad request is sent from postman to the relevant microservice through the feign client a 500 internal server error is shown instead of 400 bad request.
I wrote a custom error decoder and called it through the feign client.
Following is the deco
public class Testerrordecoder implements ErrorDecoder {
#Override
public Exception decode(String methodKey, Response response) {
return errorStatus(methodKey, response);
}
}
and I call the custom decoder as follows
FeignClient=Feign.builder().errorDecoder(new Testerrordecoder()).decoder(new JacksonDecoder()).encoder(new JacksonEncoder()).target(FeignClient.class, "http://localhost:8100/");
Expected result is 400 bad request but output is 500 internal server error. How can I correct this?
Related
Server Side
public class MyServices : Service
{
public object Get(Hello request)
{
throw new InvalidOperationException("test error message");
//return new HelloResponse { Result = "Hello, {0}!".Fmt(request.Name) };
}
}
Client Side
try
{
var client = new JsonServiceClient("http://localhost:28586/");
var response = client.Get<HelloResponse>(new Hello { Name = "DHJ" });
}
catch (WebServiceException ex)
{
// ex.ErrorCode = "InvalidOperationException" // No Problem.
// ex.ErrorMessage = null // always null. Why?
}
And i saw the docs of ServiceStack like below:
Throwing C# Exceptions
In most cases you won’t need to be concerned with ServiceStack’s error handling since it provides native support for the normal use-case of throwing C# Exceptions, e.g.:
public object Post(User request)
{
if (string.IsNullOrEmpty(request.Name))
throw new ArgumentNullException("Name");
}
Default Mapping of C# Exceptions to HTTP Errors
By Default C# Exceptions:
Inheriting from ArgumentException are returned with a HTTP StatusCode of 400 BadRequest
NotImplementedException or NotSupportedException is returned as a 405 MethodNotAllowed
AuthenticationException is returned as 401 Unauthorized
UnauthorizedAccessException is returned as 403 Forbidden
OptimisticConcurrencyException is returned as 409 Conflict
Other normal C# Exceptions are returned as 500 InternalServerError
This list can be extended with user-defined mappings on Config.MapExceptionToStatusCode.
Your HelloResponse class needs a ResponseStatus property, from the Error Handling docs:
Error Response Types
The Error Response that gets returned when an Exception is thrown varies on whether a conventionally-named {RequestDto}Response DTO exists or not.
If it exists:
The {RequestDto}Response is returned, regardless of the service method's response type. If the {RequestDto}Response DTO has a ResponseStatus property, it is populated otherwise no ResponseStatus will be returned. (If you have decorated the {ResponseDto}Response class and properties with [DataContract]/[DataMember] attributes, then ResponseStatus also needs to be decorated, to get populated).
Otherwise, if it doesn't:
A generic ErrorResponse gets returned with a populated ResponseStatus property.
I'm working on a node.js server using express and a android native app, using Retrofit 1.9.
For a login API that returns only a true/false answer to the client, should JSON still be used?
As I see it, the server has only to send a status code response:
if(isLegal) {
res.sendStatus(200);
dbConnector.updateUser(token);
}
else{
console.log('Token is not legal');
res.sendStatus(403);
}
But the Retrofit framework tries to convert the response to JSON, which makes me think I must send a JSON object with the answer, though it seems weird.
My retrofit restClient:
public class RestClient {
private static final String URL = SessionDetails.getInstance().serverAddress;
private retrofit.RestAdapter restAdapter;
private ServerAPI serverAPI;
public RestClient() {
restAdapter = new retrofit.RestAdapter.Builder()
.setEndpoint(URL)
.setLogLevel(retrofit.RestAdapter.LogLevel.FULL)
.build();
serverAPI = restAdapter.create(ServerAPI.class);
}
public ServerAPI getService() {
return serverAPI;
}
}
And usage:
restClient.getService().login(token.getToken(), token.getUserId(), new Callback<Void>() {
#Override
public void success(Void aVoid, Response response) {
Log.d("Chooser", "Successful login on server.");
}
#Override
public void failure(RetrofitError error) {
error.printStackTrace();
Log.d("Chooser", "Login failed on server.");
}
});
Using it as it is results with the following error:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
There are many topics on this issue but no certain answer about the correct (or better) method to use.
Any ideas about the best implementation in these cases?
Sending an empty body with your HTTP response is perfectly legal and some clients may care only about the response status but some clients may expect to get a response so sending a body never hurts and sometimes may be useful.
You can include a JSON response in addition to the HTTP response status:
// Express 4.x:
res.status(403).json({error: 'Token is not legal'});
// Express 3.x:
res.json(403, {error: 'Token is not legal'});
Such an error message can be very useful for the client development. You can get 403 for many reasons, illegal token, expired token, a legal not expired token but for the wrong user that doesn't have some privilege - adding a specific error message in addition to the HTTP response code can tell the client what exactly went wrong and allows the client-side code to show a better error message to the user.
Also, note that true and false are also valid JSON.
I am doing authentication for REST Services.
So If user is unauthenticated then I want to send the user as "unauthenticated user" as repsonse in JSON format.
below is my code . I have set the content type as APPLICATION_JSON then I am getting the response as syntax error on postman tool. I can see the exact error in plainText or in Xml but not able to see the response in JSON.
Could anybody help me to get out from this issu please.
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("Connection", "keep-alive");
response.setContentType(MediaType.APPLICATION_JSON);
String msg = authException.getMessage();
response.getOutputStream().println("{ \"error\": \"" + msg+ "\" }");
}
}
I think you are doing it in wrong way the method syntax in ServeletResponse class is:
void setContentType(java.lang.String type)
so it should be like this
response.setContentType("application/json;charset=UTF-8");
Hope this helps.
I have a Spring MVC 4 app with Spring Security 4 and is deployed on Tomcat 8 running under jdk 1.8. The web-service has the controller defined as such:
#RequestMapping(value = "/build", method = RequestMethod.POST, produces = "application/json", headers =
{ "Accept=*/*", "Content-Type=*/*" })
public SubjectEntity build(#RequestBody SubjectImportDTO subjectImportDTO)
{
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
User user = null;
if (principal instanceof User)
{
user = ((User) principal);
}
SubjectEntity entity = service.build(subjectImportDTO);
System.out.println("FINISH: build");
return entity;
}
I am getting a csrf token, I have that setup correctly. I know the url is getting called correctly because I can see that in the logs when I get there. The service on the back-end is running, data is correctly entered into the database, I correctly get the write object, and using the Jackson Mapper, the object 'SubjectEntity' should be translated into JSON and sent back to the requesting client. This web-service has been unit tested under the Spring Web Test framework, and it works great!
So, I am familiar with an HTTP 404 error in not finding a URL when the wrong parameters are passed in, or you're trying to do a POST when it's a GET, etc. So many reasons why we can get a 404 error ...
BUT ... IN THIS CASE ... We've already gotten to the URL, executed the code, and then it has the data it needs. Since the Controller says we have content-type / and it produces application/json, I don't know what else could be wrong?
Any ideas?
You should add #ResponseBodyto your method. without this, Spring mvc tries to find another handler method which can send a response.
NB: #RestController automatically add #ResponseBody on each method in a controller.
I need to send a stub response over http to a requesting client from Jetty. It works when I run the Junit test independently, implies, I get the correct XML response .. but it fails when I run the same thing from maven. The error I see is "java.net.SocketException: Unexpected end of file from server". I have tried everything! Please help!
Here's my code -
Junit (when run as a Junit test - it works)
public class MyTest {
#Test
public void testGetOpenLots() throws Exception {
// create fixture
MyService fixture = new MyService();
// create jetty server instance
Server server = new Server(8080);
// set a handler
server.setHandler(new HelloHandler());
// set shutdown conditions
// server.setStopAtShutdown(true);
// start server
server.start();
// invoke operation
MyResponse result = fixture.getWeather(someDummyRequest);
assertNotNull(result);
}
}
Somewhere down the line, inside getWeather(), I create a URL object and pass the URL http://localhost:8080 to it and send the request to that URL. At this point, I expect that the HelloHandler's handle method will get invoked and will write this dummy XML response to stream and getWeather() method will receive the response.
Here's the handler:
public class HelloHandler extends AbstractHandler {
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("application/xml;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
response.getWriter().println("<result>a simple response</result>");
}
}
When I run the same thing from maven, it throws the error mentioned above. What am I doing wrong?
Instead of implementing your own jetty handler you can try Jadler (http://jadler.net), an http stubbing/mocking library I've been working on for a while.