Objective
When a person creates a resource (no need to connect), she receives a unique token, which she must then transmit to each request she sends for information about her resource.
Question
There is a simple way to do that with Spring? Indeed, all tuto I found and read used an authentification with username and password.
Already tried
My first idea was to create a token at the end of POST methods (store it into database), put it into each GET requests and check if requestToken == databaseToken.
However, I don't think that's the best way to do it.
So, can you help me and advise me to solve the problem?
Thanks a lot!
There are multiple ways.
Using the #SessionAttributes annotation:
The first time our controller is accessed, Spring will instantiate an instance and place it in the Model. Since we also declare the bean in #SessionAttributes, Spring will store the instance.
You will get it inside controller's handler method thru #ModelAttribute.
Or, you can try this route:
#RequestMapping(value = "/test")
public String handler(HttpSession httpSession) {
httpSession.getId(); //this will give you unique identifier that you can set back to object that you send to front end and can share the same ID between requests.
}
https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html#getId--
Related
I am building the restful web service. For the put request, I first find the testBean with the id in the pathvariable. If it does not exist, then I create a new one. I am wondering if it is right to create a new one here, or I should throw the exception. Because id is auto increment, if I create a new TestBean, the id saved in the db is different from the one from the url path parameter.
#PutMapping("/Test/{id}")
public TestBean updateTestBean(#PathVariable long id, #RequestBody TestBean newTestBean) {
return testBeanService.getTestById(id)
.map(testBean -> {
testBean.setBRR(newTestBean.getBRR());
testBean.setModifiedDate(newTestBean.getModifiedDate());
return crewsBeanService.saveTestBean(testBean);
})
.orElseGet(() -> {
newTestBean.setId(id);
return testBeanService.saveTestBean(newTestBean);
});
}
I'd always prefer to keep PUT method idempotent. Idempotency can be explained as how many times you apply a certain "operation", the result will be the same as the first time. Since REST is just a style, it's up to you, but I will always question to me if it makes sense to keep the operation as PUT or POST.
What if the client of your service is impatient and access your PUT service multiple times while the first request is being served?. You may end up creating two users. So throwing an exception is meaningful if the ID doesn't exist.
It can be 400 or 404, I don't prefer 404 but prefer 400 because of the following reasons,
1) It confuses the client of your APIs if the resource is wrong or the ID they are using is wrong.
(You can always differentiate in your error response and provide meaningful information, but still, I don't prefer!)
2) By using 404,
you're telling the user the problem could be permanent or temporary
,for instance, say your service is not properly registered with discovery server(eureka) or is crashed, the discovery server will send 404 until you fix the problem.
By using 400,
you're asking the user to try with different input, in this case, with a different ID. This is permanent...
as you said id is auto-increment and the client cannot decide the value, so until the user fixes the problem by going back and request your POST service for a new ID, the request is "BAD" and cannot be processed.
Based on Single Responsibility Principle, you should have methods which are doing only one thing. So for your question, you need 2 methods for each request:
GET - asking the server for an object, in your case TestBean.
POST - save new objects (you don't need an id for these).
And in your front end application you could use the GET to ask the server if it have the requested object, and if not, maybe you can add a form which on submit will make the POST request with the data provided in the form fields.
PUT should only be responsible for updating a record. If the id of your bean doesn't exist, you will have an exception on your persistence layer. You can catch that exception on your API and return one of the 400's response code, such as BAD REQUEST.
For creation you should use POST, an id should not be provided in that case
This would be the RESTful way of doing this.
404 is the correct return code for a PUT to a non-existent resource, because the URL used does not address an extant resource.
If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
If the server desires that the request be applied to a different URI, it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.
https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
I'm trying to create a visualisation of REST calls among several internal and external services/servers. I'd like to know which endpoint called which other endpoint. I figured that the only way to do this is to do this on the caller side, because the receiver does not have any information about the caller endpoint.
Here's my thinking:
I create an object like RestTemplate and call the method.
I create an Interceptor or something like that, which will extract the information from the RestTemplate.
My problem is that I'm not sure how to find out which REST endpoint called the RestTemplate method. The RestTemplate (or other similar object) call could be called in nested methods, so for example the endpoint could invoke a private method, which then calls the external service itself.
Is there any way how to get this information? Or am I maybe just thinking too hard and there is an easier way to do this?
Example:
#GetMapping("/hello")
public String hello() {
methodThatCallsOtherEndpoint("something.com/weather"); // this method inside itself calls an endpoint
logRestCall("localhost:8000/hello", "something.com/weather"); // how do I do this automatically without having to type it myself?
return "hello";
}
Thanks for any help.
If these services/servers have a static IP you can possibly, tag them by their IP address?
You can use Spring Sleuth to trace the relationship between different REST calls.
I am trying to build a simple register/log-in system for an Android app, using Spring boot. I have a MySQL database in a virtual machine that contains a table with columns id, username, password. The Spring boot application contains the following classes; Account (the entity), AccountRepository (the repository), AppConfig (the configuration class) and Application (main class). My endpoint is /accounts. If I want to see what accounts are currently registered I simply go to http://<ip address>:8080/accounts for a JSON representation of the database.
I want to modify my Android program so that if a user tries to register an account, it first checks to see if the username is already registered. The problem is that I'm not able to reference a username in the web repository - I have to use the account ID (e.g. http://<ip address>:8080/accounts/2).
Is there a way to modify my Spring boot application to allow me to reference usernames directly rather than through their IDs? So rather than having my Android app looping over each database entry I can send a request to a URL such as http://<ip address>:8080/accounts/johnstone01 to see what response I get (if the response is 200 for instance then I know that the username already exists and consequently make the user choose a different username).
Highly appreciate any advice.
I suggest create POST request http://<ip address>:8080/accounts for creating account and make username checking inside. It might be MySQL-level checking using constraints.
As for separate checking of username existence I suggest to modify GET request by adding query parameter "username":
http://<ip address>:8080/accounts?username=johnstone01
in this case response will return array with only one record or will return empty array if such username does not exist.
I understand that you're making a REST API for your server. In this case the right way to do is to create an endpoint that will accept a POST request (e.g. POST http://:8080/accounts the post request will contain user informations).
From your app if someone tries to register a new account you'll send a POST request to the endpoint you defined with the information to create the new account. All the rest will happend in your service layer. It seems that you don't have one, it's ok for a small project, I guess the service code is in your controller. This mean your controller have the responsibility to check if the entity can be persisted and if yes, will do so.
In your repository just add a method that will accept as a parameter the username and return the entry for that username or null. This way your controller can request it, if it's null then it can persist the new entity and return a HTTP code 200 if not it should return a 409 Conflict code.
Your app then only have to check the return code to know what happend.
I'm trying to create a REST API following the HTTP method semantics but I got stuck with the DELETE method.
In my use case, the service is behind a gateway that authenticates the user. This service uses a SSO token that then is used to authenticate the user and get his details. From this point, I'm trying to make a call to my service where I use the id of the resource I want to delete as a path variable but then I don't know how to pass the id of the user for validation.
I've read many posts about the problems of adding a body to a DELETE method. I also think adding a custom header to identify the user is not the right way. Out of the options I have, I think only 2 are sensible:
Issue a POST request with the user id as the body. I don't like this one because I'm basically using POST with an identified resource and because semantically sounds wrong to me.
Make the request so the user id is a path variable. It would look like this. path/to/service/resourceId/{resourceId}/userId/{userId}. My problem with this one is that in the POST and PUT requests, the userId is part of the body. The API wouldn't look consistent but I guess I could still change the other 2 so the user id is also part of the url.
Any suggestions?
You should use HTTP header param for passing user token.
#DELETE
#Path("/{id}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Info deleteInfo(
#HeaderParam("Authorization") String token,
#PathParam("id") Long id){
}
HTTP authentication, maybe? That's what it is for, no? See RFC 7235.
Well, this is from a developer newly using Play. When it came to using session, I found its not at all like I have been doing in servlets or jsps.
I have tried reading documentation and found session in Play are stored in HTTP cookies rather. I have tried importing HTTP class of play.
My problem however is I am unable to initialise a new session to set values in it.
I have obviously tried using 'new' session as in Java and that obviosly didnt work out.
Session session = new session();
Also after looking somewhere I have used:
Session session = Http.Context.current().session();
which shows me error in identifying context and current
I have tried looking at sample codes and codes on net. each of them however is different and I don't get the basic way of using sessions in Play, so that after that I can use put and get to keep and retrieve.
I know the question seems too basic but believe me there is no exact answer available anywhere to what I need. So please help me regarding this.
Any answer, any piece of code, or any Link on this will be highly appreciated.
Forget everything about the sessions from the jsp and servlets world while working with the Play's session. Play doesn't store anything on the server side and by design it's completely stateless. The Play session is just a cookie attached to every http request and it's stored on the client side. Word 'session' may be misleading in your case.
Working with the session is pretty straight forward. All you need is inherited from play.mvc.Controller which you have to extend when creating your own controller. To put a value in it you simply call the session(String key, String value) method from within a controller. For example:
public class Application extends Controller {
public static Result login() {
session("key", "example value");
return ok("Welcome!");
}
}
If there is no session cookie stored on client side this method will create new one and attach it to the HTTP response. Otherwise it will modify the existing one.
To read stored value use:
String value = session("key");
You can also remove value from the session:
session().remove("key");
or completely destroy it:
session().clear();
These are helper methods to work with the particular cookie witch in Play's terminology is called session. Nothing stops you from creating another cookie with similar purpose. But it'll require more writing. These helper methods saves your time and in many cases are more than enough.
You can specify session cookie name in your application.conf by setting session.cookieName property.
In play 2.8 the Http.Context was deprecated. This means, among other things, that the method "session()" is no longer available in a controller.
This is the updated way of doing it:
public Result info(Http.Request request) {
//This is the equivalent to the old session()
request.session() ...
}
The Http.Request needs to be passed down through the route defined in routes. More information here.