I have made a REST client-server, and everything works more or less fine. Here is the dilemma: I have an option to retrieve user by its username, which works fine when the user actually exists. However, when he doesn't, i get 204 http code, which is fine, since I made a null return. I would like my method to return a plain string to client console when no user is found, say, "No such user found...", but the method return type is User (class) logically, to return a user object when such is found.
Here is the server side:
#GET
#Path("/{uName}")
#Produces({ "application/json", "application/xml"})
public User getUserByUsername(#PathParam("uName") String uName) {
returnAll = usrList.getUsers();
for (User u : returnAll) {
if (u.getUserName().equals(uName))
return u;
}
return null;
}
And here is the relevant part of client:
case 3:
sc.nextLine();
System.out.println("Enter username");
userName = sc.nextLine();
restConnect("http://localhost:8080/rest/user/"
+ userName, "GET");
promptKey();
Changing a method to return a String type would obviously disrupt the code when user is actually found. What can I do to make two type return function? Thanks
EDIT:
When user was found, my method would return the first user in list with get(0) which is wrong. It was a residue of me testing something with the ID's
EDITx2: working client
case 3:
sc.nextLine();
System.out.println("Enter username");
userName = sc.nextLine();
try{
restConnect("http://localhost:8080/rest/user/"
+ URLEncoder.encode(userName, "UTF-8"), "GET");
}
catch(RuntimeException e){
System.out.println("No such user...");
}
promptKey();
Your code should be returning a 4xx error when the user does not exist and the client should have a branch when an error is returned.
Think about how things should work for a client that you did not develop yourself and the definition of the API will probably be more clear.
See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html for additional result code details.
Related
I'm struggling to build a simple login method. (the worst thing is that I think the answer may be pretty obvious, so sorry for anything)
I have a type Client that has the client properties (name, email, username, password, age, etc.), that is storaged in a ClientRepository class. My idea is to compare the user and password til I have the right match and return the object Client logged, so I can access its properties outside.
I have two questions:
1 - The method below must have to return a Client type so I can access its properties later, right? Or theres a better way of doing a login method?
2 - What do I return in the "elses" below (when the login fails)?
Thanks
public Client logIn(String user, String password){
Cliente logged;
for(int i = 0; i < clients.size(); i++){
if(clients.get(i).getUser().equals(user)){
if(clients.get(i).getPassword().equals(password)){
logged = clients.get(i);
System.out.println("LOGIN SUCCESFULL");
return logged;
}else{
System.out.println("WRONG PASSWORD!");
}
}else{
System.out.println("USER DOESNT EXISTS");
}
}
}
I am testing a new functionality in my web app where i'm allowing the user to remain signed in even after the browing session expires. In order to achieve this, i have a "Keep me logged in" checkbox on my login page. Upon successful login, a cookie is created containing the userID and the login process continues normally. The first thing the first method in my main controller does is check for the presence of that cookie, read the userId in it, set the User object in the session correctly and bypass the login process, going directly to the home page. When the user signs out, the cookie is recreated with an expiration of 0 which means it's automatically deleted.
My Spring sessions last 30 minutes currently. I have successfully tested everything but i'm trying to replicate the Spring session expiring, which gets rid of the User object in memory and would normally force the user to login. In order to replicate it, i am deleting the JSESSIONID cookie from Chrome. When i do that, the HttpServletRequest object (which I am checking cookies on) is null.
Here is the first code that runs in my main controller :
#RequestMapping(value = {"/"}, method = RequestMethod.GET)
public String home(ModelMap model, HttpServletRequest request)
{
if (session.getAttribute("loggedInUser") != null)
{
return "home";
}
else
{
String userId = null;
for (Cookie cookie : request.getCookies())
{
if (cookie.getName().compareTo("MDHISStaySignedIn") == 0)
{
userId = cookie.getValue();
break;
}
}
if (userId != null)
{
session.setAttribute("loggedInUser", userService.findByUserId(userId));
return "redirect:/";
}
else
{
model.addAttribute("login", new Login());
model.addAttribute("register", new Register());
model.addAttribute("registering", false);
return "login";
}
}
}
Is it normal that my request object is null when deleting this cookie? Am i not correctly replicating the Spring session timing out by deleting it? This NullPointerException only happens when deleting this cookie and upon first running the web app, the controller does not thrown the exception when the cookie is created by the first run. Should i somehow be checking for this null value and redirecting the controller back to this method if it is?
Thanks!
The solution is to add the following method parameter :
#CookieValue(value = "MDHISStaySignedIn", defaultValue = "notFound") String cookie
This will assign the content of the cookie to the value if it's present and assign "notFound" if it is not. This way one can access cookies when the request object is null!
EDIT: Alex Martelli Gave me a great answer which I changed only slightly in order to get working properly for me
The answer to this problem for me was
public boolean Login2(String usernamein, String passwordin) {
DatastoreService datastore = DatastoreServiceFactory
.getDatastoreService();
Filter usernamefilter = new FilterPredicate("username",
FilterOperator.EQUAL, usernamein);
Query validuserquery = new Query("Users").setFilter(usernamefilter)
.setKeysOnly();
Entity theUser = datastore.prepare(validuserquery).asSingleEntity();
if (theUser == null) {
System.out.println("Username not found");
return false;
}
return true;
}
End of EDIT
Original Post
Okay so I have spent the entire day trying to do this and have tried my best to research it but I can't do it! :(
I feel like there is probably and easy answer but I can't work it out, I feel like I have tried Everything! please please please help D:
I have a Login section of code on its own .jsp page called Index.jsp
String username = "";
String password = "";
try {
if (request.getParameter("usernamein") != null && request.getParameter("passwordin") != null) {
username = (request.getParameter("usernamein"));
password = request.getParameter("passwordin");
if(login.Login2(username, password)){
response.sendRedirect("Race.jsp");
System.out.println("go to next page");
} else {//need username/password
out.println("your username or password is incorrect");
}
}
} catch (Exception e) {
out.println("problem in getting u an p error =" + e);
}
Part way through that code is the line (login.Login2(username, password))
that code calls a method in a class using java use bean thingy
the method it calls is this:
public boolean Login2(String usernamein, String passwordin) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Filter usernamefilter = new FilterPredicate("username", FilterOperator.EQUAL, usernamein);
Query validuserquery = new Query("Users");
validuserquery.addProjection(new PropertyProjection("username", null));
System.out.println(validuserquery);
List<Entity> list = datastore.prepare(validuserquery).asList(FetchOptions.Builder.withLimit(100));
System.out.println(list);
for (Entity username : list){
System.out.println("username is equal to '"+username+"'");
if(username.equals(usernamein)){
return true;
}else
System.out.println("was not equal");
return false;
}
return false;
}
I'm trying to only go to the next page in the top code if the if statement is true, meaning that the username does exist, eventually I want it to only go to then next page if the username and password are both in the same entity i.e. the combination exists.
I hope you guys understand what i am trying to do and can help me
oh the System.out.println() for the username value outputs this:
username is equal to '<Entity [user("id")/Users(5910974510923776)]:
username = RawValue [value=[B#187c4d7]
>
'
If you need any more info just ask and i'll add it to the post :D ty
You would be best advised to query the datastore for just the username of interest...:
Query validuserquery = new Query("Users").
setFilter(new Query.FilterPredicate("username",
Query.FilterOperator.EQUAL,
usernamein)
).setKeysOnly();
Entity anyentity = datastore.prepare(validuserquery).asSingleEntity();
if(anyentity == null) {
System.out.println("was not equal");
return false;
}
return true;
This assumes there are no entities with duplicated username in your store (though you could deal with that by catching exception PreparedQuery.TooManyResultsException -- if that gets raised, it means you have more than one entity with that username, so that would be a return true case too:-).
The core idea is: getting every user entity and checking their usernames in your application code is really wasteful of resources (quite apart from the bugs in your code in this case) -- use queries to get only the relevant entity or entities, if any!-)
Try searching a bit more next time. It's not that hard, your issue was pretty easy. In any case :
Your query returns a full object, not just properties of your object. You need to do
entity.getProperty("username")
So that you see your property, not the full object.
More info here.
I am trying to reset password for SAP using bapi but i am getting error as "password is not type of field input".
I am posting my code below.
Here getRandomString() is user defined function. I have copied this code from Internet and I am unaware about this.
String newPassword = getRandomString();
try{
JCO.Function bapiUserChange = repository.getFunctionTemplate("BAPI_USER_CHANGE").getFunction();
if(bapiUserChange != null){
JCO.ParameterList userChangeInput = bapiUserChange.getImportParameterList();
JCO.Structure sPassword = userChangeInput.getStructure("PASSWORD");
//sPassword.setValue(newPassword, ????) //what do I assign it to?
userChangeInput.setValue(userId, "USERNAME");
userChangeInput.setValue(newPassword, "PASSWORD"); // this gives an error
userChangeInput.setValue("X","PASSWORDX"); //I know "X" is true, this will give an error too I believe
mConnection.execute(bapiUserChange);
//send E-mail
boolean emailSent = sendEmail(userId, newPassword, "XXX200");
msgMgr.reportSuccess("Password Reset Done");
if(mConnection != null){
mConnection.disconnect();
}
}
}catch(Exception e){
msgMgr.reportException("Could not change password " + e.getMessage(),true);
}
but String newPassword = getRandomString(); here it is giving error because getRandomString() is user defined function and i am unaware about this.Is there any role of this while reseting password or I can directly use String newpassword=" ";
The parameter PASSWORD is typed as BAPIPWD which is a structure what in turn contains only a single field named BAPIPWD. Therefore, you need to access the structure approximately like this:
JCO.Structure sPassword = userChangeInput.getStructure("PASSWORD");
sPassword.setValue(newPassword, "BAPIPWD");
Try using BAPIPWD or PASSWORD-BAPIPWD instead of PASSWORD, and just in case make sure the password is all caps
I am trying to reset password for SAP using bapi but i am getting error as "password is not type of field input".
I am posting my code below.
Here getRandomString() is user defined function. I have copied this code from Internet and I am unaware about this.
String newPassword = getRandomString();
try{
JCO.Function bapiUserChange = repository.getFunctionTemplate("BAPI_USER_CHANGE").getFunction();
if(bapiUserChange != null){
JCO.ParameterList userChangeInput = bapiUserChange.getImportParameterList();
JCO.Structure sPassword = userChangeInput.getStructure("PASSWORD");
//sPassword.setValue(newPassword, ????) //what do I assign it to?
userChangeInput.setValue(userId, "USERNAME");
userChangeInput.setValue(newPassword, "PASSWORD"); // this gives an error
userChangeInput.setValue("X","PASSWORDX"); //I know "X" is true, this will give an error too I believe
mConnection.execute(bapiUserChange);
//send E-mail
boolean emailSent = sendEmail(userId, newPassword, "XXX200");
msgMgr.reportSuccess("Password Reset Done");
if(mConnection != null){
mConnection.disconnect();
}
}
}catch(Exception e){
msgMgr.reportException("Could not change password " + e.getMessage(),true);
}
but String newPassword = getRandomString(); here it is giving error because getRandomString() is user defined function and i am unaware about this.Is there any role of this while reseting password or I can directly use String newpassword=" ";
The parameter PASSWORD is typed as BAPIPWD which is a structure what in turn contains only a single field named BAPIPWD. Therefore, you need to access the structure approximately like this:
JCO.Structure sPassword = userChangeInput.getStructure("PASSWORD");
sPassword.setValue(newPassword, "BAPIPWD");
Try using BAPIPWD or PASSWORD-BAPIPWD instead of PASSWORD, and just in case make sure the password is all caps