Spring, Angular JS and exception handling in the service layer - java

Our development team is building an application that uses jasper-reports 6.2.0, spring-mvc 3.2.14, java-ee-7, tomcat 8 and in the front-end we use angularjs. Our rest requisitions are all made via ajax.
The application is entirely built to receive json objects as response for our requisitions, because our requisitions via angularjs are all made via Ajax. In a specific application feature we have a regular get requisition using window.location = url, because we need to return a streaming which is nothing more than a byte array containing a PDF file content.
That being said, when we have a back-end error while generating this PDF file our application redirects user to a blank screen with a json object printed in it.
I've already had experience in spring-mvc exception handling globally ou per exception case, using exception handling with ExceptionHandler annotation or per ControllerAdvice to generalize the exception handling, but always handling classes in the controller layer annotated with Controller returning a ModelAndView object, but never classes in the service layer annotated with Service.
My question is how to capture a exception and make the application redirects users to a error screen with some parameterized message when we have regular get requisitions.

In my experience, and even if it's not exactly an answer to the question, main issue is not server side but client side :
stop doing window.location = url to download Content-Disposition:attachement files in an RIA application. Particularly when the download can cause errors thrown to the client. really.
Libs like fileDownload ( https://github.com/johnculviner/jquery.fileDownload ) allow to download the file in background, avoiding all the mess when an error append, and the UI freeze waiting for the server response.

So lets say you want to take care of exception on client side on the basis of http status code then you can make a interceptor like :
var app = angular.module('appname',[]);
app.factory('myHandler', function ($injector) {
var interceptor = {
response: function (response) {
.
.
.
return response;
},
responseError: function (response) {
if (response.status == 401) {
location.href = "#/error";
}
else if(response.status == 403){...}
else if().....
return response;
}
};
return interceptor;
});
and inject it in your application as :
app.config(function ( $injector) {
$httpProvider.interceptors.push('myHandler');
...
});
now every request would first go here , check if error status or whatever you want it to and then if no error (in which case you dont change location.href) it continues ,magically to wherever it was going else goes to specified templateURL on the basis of routeProvider.
Helpful links injector, httpProvider

Related

How to get "POST" method to show with Rest Web Services

I am new to Rest web services, and I am trying to figure out what I am doing wrong. When I run on server with the address:
localhost:8080/rest/webresources/error
Then the output message I want (the error message) shows up.
But when I run on the server to show input values using:
localhost:8080/rest/webresources/inputvalues
it doesn't. What am I doing wrong? I feel like my path is wrong, and I tried different combinations of it, but it still gives me a 404 not found error.
#Path("error")
public class RestWeb {
#GET
#Produces(MediaType.TEXT_HTML)
public String getText() {
return "<body> Error. Invalid data. </body>";
}
#POST
#Produces(MediaType.TEXT_HTML)
#Path("/inputvalues")
public String getParamText(#FormParam("travel") String travel,
#FormParam("start") String start,
#FormParam("duration") String end,
#FormParam("party") String people) {
String returnString = processInput(travel, start, end, people);
return "<body> " + returnString + " </body>";
}
Assuming that the REST services were correctly written and deployed, the problem here is the lack of understanding of the way a POST Rest Service is expected to behave as.
From the comment section above it is clear that you are trying to call a POST API directly from a browser.
That can be done fine for a GET type of a service but won't work for a POST type service.
Reason
The REST API uses several HTTP methods to perform various actions on REST resources. Any REST API that uses a GET call can be invoked using a web browser.
A post service however expects a certain set of input parameters (Here in your case, form params "travel", "start", "duration" and "party" are required)
You cannot call POST API's directly by simple typing the path of the Service URL in the browser.
You can use tools like POSTMAN, RESTer and a lot of such software available on the web, with extensive tutorials on how to use these for POST type REST API calls.

Javalin sessionAttribute() isn't Persisting Between Requests

I'm setting up Javalin as a microservice, providing API endpoints for my React app. Locally, Javalin is running on port 7070 and React is running on 3000 (via the built-in server with create-react-app).
I'm attempting to wire up the login/logout services, and in my login controller I have this code.
boolean isValid = User.isPasswordValid(u, password);
if (isValid)
{
ctx.sessionAttribute("currentUser", u.userHash);
}
In the React code, it listens to the success response from this controller and then reroutes to the /dashboard page. The /dashboard page loads up data, and I'm getting the data appropriate for the user by getting that userHash out of the Session like this:
String userHash = ctx.sessionAttribute("currentUser");
However, this is always returning null.
It seems like this should work, and even matches the tutorial code posted on the Javalin website https://javalin.io/tutorials/website-example
Is the fact that the React code and the Javalin running on different servers cause this to not work? I tried replacing the sessionAttribute() with cookieStore() and it has the same null issue.
Edit - Adding The Reponse information showing a JSESSIONID
After discussing with the Javalin creator, the correct answer is to include this line in the server creation:
app.before(ctx -> ctx.header("Access-Control-Allow-Credentials", "true"));
and ensure your JavaScript call includes the option:
credentials: "include",

REST request failure through filter

I have a simple REST client with some basic functionality, and so far I'm stuck as I don't know how to process those request and send them correctly into the server. So far I've tried this in the filter, without any luck.
if (!request.getHeader("/rest/").equals(null)){
String loginForm = config.getInitParameter("LoginParam");
res.sendRedirect(req.getContextPath() + loginForm);
return;
}
And I get the following error because of that deny.
Exception in thread "main" org.jboss.resteasy.client.ClientResponseFailure
How should I check that the request is coming from the REST client so I can let it pass through?
I'd normally add header Accept: application/json (or xml or whatever) to indicate the client wants to get data as oppose to HTML.

Make Call to Back-end, Multiple Path Variables, Ext Js

I've got a RESTful call that I'd like to make to the back end of my application. The front end is written in Ext JS (JavaScript) the back-end in JAVA utilizing Hibernate. The application utilizes the MVC design pattern.
On the back end, I've got a GET request endpoint with a "mapping" akin to: thing/{thingOne}/otherThing/{thingTwo}.
Ext JS provides a number of functions on their stores for hitting a back end through a model's proxy: .load(), .save(), .remove(). Each of these is able to take multiple arguments for their [options] parameter; however, I am attempting to find documentation that shows me how to make a multi-parametered request to a back-end GET endpoint and have found none, so far.
My assumption is that the call would be structured like: .load("param1", "param2") based upon the documentation for .save() and .remove(). Here's the doc. for save, for remove, and load.
So, how do I make a GET call to the back end with multiple parameters? Am I even in the correct ballpark?
You can use "extraparams" on proxy.
sencha api 4.2.2 - extraparams on store
var formOperation = [];
var example = {"city":"Manchester"};
Ext.Object.merge(formOperacion,example);
store.getProxy().extraParams = formOperation;
store.load();
Another solution:
Sencha api - store - Dynamic Loading
store.load({
params: {
group: 3,
type: 'user'
},
callback: function(records, operation, success) {
// do something after the load finishes
},
scope: this
});
Build the request's URL as a concatenated string, including the arguments:
var requestUrl = 'thingOne/' + thingOneVar + '/otherThing/' + otherThingVar;
Note that whether your "built" string should be prefixed with a / depends upon how your model's proxy is configured. Essentially, you are aiming for a legitimate request url.
And make a request via the proxy (here, I'm using AJAX):
Ext.Ajax.request({
url : requestUrl,
// ....
});
The then needs to be handled by a callback or as a promise.

Play-Framework & Ajax how to?

I'm looking to do the following with AJAX...
I have a request to my server that takes a considerable amount of time to complete. The request is made in the controller and upon completion a HTML page is loaded informing the user of its completion.
However, what I'd like to do is have the request sent asynchronously, load the completion page and then load the requests result once it become available. I assume I would use AJAX to do this but I'm not exactly sure how. Can anyone point me to a good guide for doing something like this?
In case my explanation above is too confusing here is what I want to do...
1) Send request to server from Controller asyncronously.
2) load HTML page.
3) When request has completed fill field in already loaded HTML page with the response from the request.
I wrote a tutorial recently that walks through how to do this with Play 1.2, JSON, and jQuery:
Tutorial: Play Framework, JPA, JSON, jQuery, & Heroku
There are 2 parts you need to take into account here:
The client side
The server side
For the client side; an Ajax request (for example, using jQuery.ajax) is per definition asynchronous. This means that you should be able to do the following - again using jQuery, which makes things easier - in your HTML page:
// The ready handler, which fires when the page has been loaded
$(function() {
jQuery.ajax(
// Do your thing here
);
});
For the server side; in case your operation is going to be running for a relatively long time on the server (for instance several web service calls or long running IO operations) you'll want to use Play's asynchronous capabilities to let the Play! server execute things as effeciently as possible. It does this by offloading the long running operation(s) to their own threads.
The only thing left to do is set-up a route to your controller, implement the handler method and render something that your client-side JavaScript code is capable of parsing (JSON is probably the easiest, using Play's renderJson()).
I haven't used this set-up myself - maybe someone can confirm this would be the way to do it?

Categories

Resources