I google this matter for hours but I still cannot find solution.
Here is my java code
#POST
public String doLogin(User user) {
System.out.println(" = " + user.getUsername());
return "";
}
and
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class User {
String username;
String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
and here is my AngularJs code
angular.module('notesApp', []).controller('MainCtrl', ['$http', function($http) {
var self = this;
self.submit = function() {
$http({
method: 'POST',
url: 'http://127.0.0.1:8080/Test/app/login',
headers : {'Content-Type': 'application/json'},
data: self.user //forms user object
})
.then(function(response) {
console.log(response.data);
return response.data;
}, function(response) {
});
}
}]);
My error message was:
SEVERE: A message body reader for Java class entity.User, and Java type class entity.User, and MIME media type application/json; charset=UTF-8 was not found, as I could not access 'user' Object in java code.
Could you please figure out which part I do wrong? Thank you so much.
You need to read from POST body and not Query Params.
You can use this:
#POST
public String doLogin( User user) {
System.out.println(" = " + user.getUsername());
return "";
}
#QueryParam is used to the queryparams which you'll pass as ?user=xyz#gmail.com
Remove query param You will get a serialized string. deSerialize it to User.
#POST
public String doLogin(User user) {
System.out.println(" = " + user.getUsername());
return "";
}
You are setting the data field on your POST. This sets the HTTP Body, not an HTTP query param.
Check the browser debugger networking panel to ensure that you are sending what you expect to the server. will open it and then 'send' your user and look at what is sent. Does this object look exactly like what User in java expects?
Related
I am currently working on a tutorial to get to know Spring Boot and currently facing the following problem.
During my registration process (works correctly -> user ends up in the database) I get the status code 200/OK in the browser console, but also an error message regarding an incorrect syntax:
My backend code looks like this:
AuthController:
#RestController
#RequestMapping(value = "/api/auth")
#AllArgsConstructor
public class AuthController {
private final AuthService authService;
private final RefreshTokenService refreshTokenService;
#PostMapping(value = "/signup")
public ResponseEntity<String> signup(#RequestBody RegisterRequest registerRequest) {
/*
* RegisterRequest: Through this class we are transferring the user details like username, password and email as part of the RequestBody (DTO)
* */
authService.signUp(registerRequest);
return new ResponseEntity<>("Registration Successful", null, OK);
}
....
AuthService:
#Transactional
public void signUp(RegisterRequest registerRequest) {
User user = new User();
user.setUsername(registerRequest.getUsername());
user.setEmail(registerRequest.getEmail());
user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
user.setCreated(now());
user.setEnabled(false);
userRepository.save(user);
String token = generateVerificationToken(user);
String message = mailContentBuilder.build("Thank you for signing up to Spring Reddit, please click on the below url to activate your account : "
+ ACTIVATION_EMAIL + "/" + token);
mailService.sendMail(new NotificationEmail("Please Activate your account", user.get
Email(), message));
}
Used DTO:
public class RegisterRequest {
private String email;
private String username;
private String password;
}
My frontend code looks like:
SignUpComponent:
signUp() {
this.signUpRequestPayload.email = this.signUpForm.get('email').value;
this.signUpRequestPayload.password = this.signUpForm.get('password').value;
this.signUpRequestPayload.username = this.signUpForm.get('username').value;
this.authService.signUp(this.signUpRequestPayload).subscribe((data) => {
console.log('Sign up successful', data);
});
}
AuthService:
#Injectable({
providedIn: 'root'
})
export class AuthService {
private headers = new HttpHeaders({ 'Content-Type': 'application/json' });
constructor(private http: HttpClient) { }
signUp(signUpRequestPayload: SignUpRequestPayload): Observable<SignUpRequestPayload> {
const body = JSON.stringify(signUpRequestPayload);
return this.http.post<SignUpRequestPayload>('http://localhost:8080/api/auth/signup', body, { headers: this.headers });
}
}
Used interface:
export class SignUpRequestPayload {
email: string;
password: string;
username: string;
}
What am I doing wrong here?
I solved it like this:
signUp(signUpRequestPayload: SignUpRequestPayload): Observable<string> {
const body = signUpRequestPayload;
return this.http.post('http://localhost:8080/api/auth/signup', body, { responseType: 'text', headers: this.headers });
}
I had to remove from the post method and set the responseType to 'text'. I also had to remove the JSON.stringify() method and set the return type to Observable.
As your response("Registration Successful") is not valid JSON.
So please remove <SignUpRequestPayload> from below line
return this.http.post<SignUpRequestPayload>
When I try to call with this.http.get and #GetMapping I am able to send the call to spring controller,
When I try to change from this.http.get to this.http.post and from #GetMapping to #PostMapping I am not able to call the spring controller /api/v1/basicauth method.
As I am having username and password I want to use PostMapping only
My code as below:-
Angular
var formData: any = new FormData();
formData.append("userName", username);
formData.append("password", password);
let params = new HttpParams();
params = params.append('username', username);
params = params.append('password', password);
return this.http.post<any>('/api/v1/basicauth', { formData }).pipe(map((res) => {
this.username = username;
this.password = password;
}));
Spring boot:-
#PostMapping(path = "/basicauth")
public AuthenticationBean helloWorldBean(#RequestBody UserDetails user) {
log.info("Start helloWorldBean method");
UserDetails.java
public class UserDetails {
private int userId;
private String userName;
private String password;
}
Do not use FormData (Angular) as your controller is accepting #RequestBody
your formData should be something like
var formData = {"username": username, "password": password};
Rest will deserilize automatically it to UserDetails class
Client side
login(username: string, password: string) {
return this.http.post<any>('/api/v1/basicauth', { username, password })
.pipe(map(user => {
// eg.
// localStorage.setItem('currentUser', JSON.stringify(user));
return user;
}));
Example from: https://jasonwatmore.com/post/2019/06/22/angular-8-jwt-authentication-example-tutorial
Server side
You are retrieving paramaters with #RequestParam, which means you're expeting parametes as http://host:8080/api/auth?password=abc&....
Please check https://www.baeldung.com/spring-request-response-body
I am trying to rewrite my login piece with Spring boot. Currently, my data is being posted fine and the backend is getting it, but my success function is not being fired. My backend is throwing no errors, but I am getting a 404 error on the browser.
Here is my post:
$.ajax({
type: "POST",
url: "login",
data: "&username=" + username.value + "&password=" + password.value
}).done(function(response) {
var resp = JSON.parse(response);
if (resp.loginResult === "false") {
//TODO
} else {
//TODO
}
});
Controller:
#Controller
#Scope("session")
public class LoginController {
#GetMapping("/login")
public String login() {
return "login";
}
#PostMapping("/login")
public String login(HttpServletRequest request) {
HttpSession session = request.getSession();
StringBuilder json = new StringBuilder();
String username = request.getParameter("username");
String password = request.getParameter("password");
if (userExists()) {
session.setAttribute("isLoggedIn", "true");
session.setAttribute("userID", username);
session.setAttribute("userType", "employee");
json.append("{");
json.append("\"loginResult\": \"true\",");
json.append("\"resultMessage\": \"Logged in\"");
json.append("}");
} else {
System.out.println("Username or password does not match.");
json.append("{");
json.append("\"loginResult\": \"false\",");
json.append("\"resultMessage\": \"Bad Login\"");
json.append("}");
}
return json.toString();
}
}
I am trying to just return a JSON string which can be parsed on the front end and do whatever needs to be done based off the resultMessage. Sorry if my code is ugly, I am still new to Spring and welcome any suggestions!
Here is the error in my console on the browser:
POST http://localhost:8080/BedrockWeb/login 404 ()
I am assuming I am not returning my JSON string properly.
If you use Spring, then use the conveniences that it provides. You can create following class:
public class LoginResult {
private boolean loginResult;
private String resultMessage;
public LoginResult() { }
public String getResultMessage() {
return resultMessage;
}
public boolean isLoginResult() {
return loginResult;
}
public void setLoginResult(boolean loginResult) {
this.loginResult = loginResult;
}
public void setResultMessage(String resultMessage) {
this.resultMessage = resultMessage;
}
}
Then you have to change your controller method to:
#PostMapping("/login")
#ResponseBody
public LoginResult login(HttpServletRequest request) {
HttpSession session = request.getSession();
String username = request.getParameter("username");
String password = request.getParameter("password");
LoginResult loginResult = new LoginResult();
if (userExists()) {
session.setAttribute("isLoggedIn", "true");
session.setAttribute("userID", username);
session.setAttribute("userType", "employee");
loginResult.setLoginResult(true);
loginResult.setResultMessage("Logged in");
} else {
System.out.println("Username or password does not match.");
loginResult.setLoginResult(false);
loginResult.setResultMessage("Bad Login");
}
return loginResult;
}
The #ResponseBody annotation tells a controller that the object returned is automatically serialized into JSON and passed back into the HttpResponse object. source
Yes, this is because you are not sending JSON response properly.
What you can do is create an object and set the values in that and then try to convert in JSON using
new JSONSerializer().transform(new DateTransformer("MM/dd/yyyy HH:mm:ss"), java.util.Date.class).exclude("*.class").serialize(object);
and send the response to AJAX like below:
return new ResponseEntity<String>(new JSONSerializer().transform(new DateTransformer("MM/dd/yyyy HH:mm:ss"), java.util.Date.class).exclude("*.class").serialize(object), HttpStatus.OK);
NOTE: If you want to do the same with Spring boot then the #ResponseBody annotation is enough. It will convert the object to JSON.
#RequestMapping(value = "/createItem", method = RequestMethod.POST)
#Override
public void createItem(#RequestParam(value="userId") String userId, #RequestParam(value="title") String title, #RequestParam(value="subtitle") String subtitle, #RequestParam(value="description") String description, #RequestParam(value="category") String category, #RequestParam(value="datapack") String datapack) {
this.itemDAO.createItem(userId, title, subtitle, description, category, datapack);
}
I am creating RESTful application with Spring. The method above works just fine, but when the datapack is longer than a certain length it will result in error. The error says...
Error parsing HTTP request header Note: further occurrences of HTTP
header parsing errors will be logged at DEBUG level.
I need to pass the datapack as a parameter and the datapack itself will be a json file which I convert it to string.
The datapack file might be very complex and big. How do I solve this?
Here's the example of the request:
http://localhost:8090/createItem?userId=test&title=test&subtitle=test&description=test&category=test&datapack=
{
"CLASS": "com.mincom.ellipse.edoi.ejb.menu_item.MENU_ITEMRec",
"INSTANCE": {
"m_creationDate": "20150824",
"m_creationTime": "001616",
"m_creationUser": "SR4187",
"m_lastModDate": "20150824",
"m_lastModTime": "001616",
"m_lastModUser": "SR4187",
"m_menuType": "",
"m_invokationString": "",
"primaryKey": {
"m_uuid": "3b4d95fe3dd3432fb00cde0cc25f903f"
}
}
},
{
"CLASS": "com.mincom.ellipse.edoi.ejb.i18n_descriptions.I18N_DESCRIPTIONSRec",
"INSTANCE": {
"m_creationDate": "20150824",
"m_creationTime": "001616",
"m_creationUser": "SR4187",
"m_lastModDate": "20150824",
"m_lastModTime": "001616",
"m_lastModUser": "SR4187",
"m_description": "CUSTOM_MENU",
"primaryKey": {
"m_locale": "en",
"m_uuid": "3b4d95fe3dd3432fb00cde0cc25f903f"
}
}
},
{
"CLASS": "com.mincom.ellipse.edoi.ejb.top_level_menus.TOP_LEVEL_MENUSRec",
"INSTANCE": {
"m_creationDate": "20150824",
"m_creationUser": "SR4187",
"m_lastModDate": "20150824",
"m_lastModTime": "001620",
"m_creationTime": "001620",
"m_lastModUser": "SR4187",
"m_uuid": "3b4d95fe3dd3432fb00cde0cc25f903f",
"primaryKey": {
"m_name": "SX"
}
}
}
Examples above works, but if I test with longer JSON file, it won't work.
Create a controller method that shall be receiving the JSON data posted by $http service using XHR (AJAX)
#RequestMapping(value = "/savecompany_json", method = RequestMethod.POST)
public #ResponseBody String saveCompany_JSON( #RequestBody Company company ) {
//
// Code processing the input parameters
//
return "JSON: The company name: " + company.getName() + ", Employees count: " + company.getEmployees() + ", Headoffice: " + company.getHeadoffice();
}
Create a POJO which maps to JSON object
public class Company {
private String name;
private long employees;
private String headoffice;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getEmployees() {
return employees;
}
public void setEmployees(Long employees) {
this.employees = employees;
}
public String getHeadoffice() {
return headoffice;
}
public void setHeadoffice(String headoffice) {
this.headoffice = headoffice;
}
}
Source
If the request is really big (like when sending files for instance), you might want to change your content-type in your http header. For instance (although might look differently depending on what you're actually sending):
$http({
method: 'POST',
url: url,
headers: {
'Content-Type': 'multipart/form-data'
},
data: {
data: model,
file: file
}
});
Then if the request is too big for the server to accept it, you might need to extend the request size limit. If you're using spring boot, you may go to your application.properties file (should be located under src/main/resources, but if it doesn't exist yet, create it manually) and add the following properties:
multipart.maxFileSize=3MB
multipart.maxRequestSize=3180KB
You are using a POST request anyhow, so simply send the parameters in the body with content type application/x-www-form-urlencoded like a normal form submission instead of in the URL.
I'm having an issue POSTing to Jersey using the following...
var details = {username: uname, password: pword};
$.post('login',function(details){
console.log("sent: "+details);
});
The correct function in my login page is being ran but both username and password are null.
The following is how I consume them...
public void login(#FormParam("username") String uname,
#FormParam("password") String pword){
System.out.println("username = " + uname + "password = " + pword);
}
I realise what I POST isn't a form but #FormParam is the only # I can see that would fit here.
EDIT
Okay, I've got the following right now...
the POST being made
var details = {'username': username, 'password': password};
$.POST('login', details,function(result){
console.log(result);
},"json");
The receiving method
#POST
public Viewable HeyStaksLogin(LoginInfo loginI){
String uname = loginI.username;
String pword = loginI.password;
System.out.println("username = ");
}
The loginInfo class
#XmlRootElement
public class LoginInfo {
public String username;
public String password;
}
The data is sent as the second argument of the $.post() function (the first being the url and the third being the success callback), like this:
var details = { username: username, password: password };
$.post('login', details, function(result) {
console.log(result);
});
#FormParam is not usable in this case, as what you are posting is JSON. Here is an example of what you could do:
1) add jersey-json.jar to your project dependencies
2) define the following bean to represent the body of the message:
#XmlRootElement
public class LoginInfo {
public String username;
public String password;
}
3) modify the login method as follows:
public void login(LoginInfo li) {
System.out.println("username = " + li.username + "; password = " + li.password);
}
try #Consumes(MediaType.APPLICATION_FORM_URLENCODED) annotation for your serverside method