I have Spring Boot project on backend and Android app on frontend. Communication between the two happens via Retrofti2. On one of the endpoits, actually /login endpoint, is retruning a HashMap<String, Object>. That endpoint looks like this:
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<?> login(#RequestBody AuthenticationRequest authenticationRequest) throws Exception {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("user", getUserObject());
map.put("token", getJwtToken());
return ResponseEntity.ok(map);
}
Interface for method call looks like this:
public interface LoginService {
#POST("login")
Call<HashMap<String, Object>> testLogin(#Body Login login); //login contains username and password strings
}
The reposnse in frontend look like this:
Call<HashMap<String, Object>> call = mLoginService.testLogin(new Login(username, password));
call.enqueue(new Callback<HashMap<String, Object>>() {
#Override
public void onResponse(Call<HashMap<String, Object>> call, Response<HashMap<String, Object>> response) {
if (!response.isSuccessful()){
Toast.makeText(getApplicationContext(), "Wrong credentials!", Toast.LENGTH_SHORT).show();
return;
}
//extract user & token
HashMap<String, Object> map = response.body();
Log.i("Test result", map.get("token").toString());
Log.i("Test result", map.get("user").toString());
User u = (User) map.get("user");
//Toast.makeText(getApplicationContext(), "Welcome " + u.getUsername() + "!", Toast.LENGTH_SHORT).show();
startActivity(goToEmailsIntent);
}
#Override
public void onFailure(Call<HashMap<String, Object>> call, Throwable t) {
Toast.makeText(getApplicationContext(), "Cannot login, look at the console", Toast.LENGTH_SHORT).show();
Log.i("ERRROOOOOOR during login", t.toString());
return;
}
});
When I look at the log statements in the console everything is okey, I get the data which I want. But when trying to cast to User object I get exception.
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.email.model.User
How to get around this? Is there any better way to send User object and a String from backend?
First method
When you can change your backend service then modify the backend service return DTO not HashMap.
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<Token> login(#RequestBody AuthenticationRequest authenticationRequest) throws Exception {
// create your response
Token token = new Token();
return ResponseEntity.ok(token);
}
Second method
Use json format to exchange data,in your onResponse method you can do like below:
HashMap<String, Object> map = response.body();
// map.get("user) may return a null value
String jsonString = new Gson().toJson(map.get("user));
User user = new Gson().fromJson(jsonString,User.class);
// do other thing as you want
Related
I've got a problem with Volley request - I want to send GET (another similiar POST also) request with JSONObject param (user having password and login) to authorize user and send back full user data. Although I can see during debugging that mRequestBody is correct JSON but I cannot receive it by my controller -
private void processLogin() throws JSONException {
this.user.setLogin(this.loginText.getText().toString());
this.user.setPassword(this.passwordText.getText().toString());
final JSONObject jsonObject = new JSONObject(new Gson().toJson(this.user));
final JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, UrlHelper.loginUrl, jsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
user = new Gson().fromJson(response.toString(), User.class);
if (user.getUserId().equals(getResources().getString(R.string.ERROR))) {
onLoginFailed();
} else {
onLoginSuccess(user);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.toString());
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
return headers;
}
};
VolleySingleton.getInstance(this).addToRequestQueue(request);
}
Controller method:
#RequestMapping(value = "/loginTest", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
public User someMethod(#RequestBody User user) throws SQLException {
return userService.authenticateUser(user.getLogin(), user.getPassword());
}
Without annotation #RequestBody I it process but User in param is empty, so I process User with null password and login. Recently I did it by StringRequest Please, help me. :)
As a part of the HTTP specs, GET requests have no body. You can create and send GET requests with a body though, but that's meaningless since the body has no semantic meaning in the GET method specification. I don't know too much about Spring, but my guess is that Spring is probably ignoring the body of the request because it's a GET method. You should send and receive the request as POST if your intention is to put something inside the body.
I was trying Post method with using Volley and I got: com.android.google.volley server error.
I tested my api in postman and it works.
Here is my code:
StringRequest request=new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("Response", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error :",error.getMessage());
}
}) {
#Override
public Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("name", film.toString());
params.put("email", spin.toString());
params.put("password", spin_iki.toString());
params.put("address", spin_uc.toString());
params.put("brand", name.toString());
return params;
}
};
RequestQueue queue= Volley.newRequestQueue(film.this);
queue.add(request);
}
});
Normally I use my api like http://myurl/api/values/Post?film=...&email=...
How can I fix this? Thank you.This my API's Post method code
[HttpPost]
public int Post_film(string name, string email, string password, string address, string brand)
{
using (var context = new Entities())
{
db_table nesne = new db_table();
nesne.name =name;
nesne.email = email;
nesne.password = password;
nesne.address = address;
nesne.brand = brand;
context.db_table.Add(nesne);
int i = context.SaveChanges();
return i;
}
}
this my Postman SS
enter image description here
OK, you're sending a POST request but still adding parameters via URL. If your server is taking these parameters from the URL, then your Volley request will never work because overriding getParams() only works for parameters inside the request body, not parameters attached to the URL. You should either change the way your server is taking the parameters or, in your Android code, generate a string URL with all the parameters attached to it like "http:://myUrl.com/?email=something&name=something". To me, the most logical option is to change your server side code, because it doesn't make too much sense to expect a POST request with parameters in the URL. Parameters in POST requests should be inside the request body,
I am new to Spring Social. I am working on java Spring Social application in which i want to be able to register through facebook. can anyone please respond with example to achieve it?
In Spring Controller callback method
#RequestMapping(value = "/callback", method = RequestMethod.GET)
#ResponseBody
public String postOnWall(#RequestParam("code") String code,
#RequestParam("state") String state, HttpServletRequest request,
HttpServletResponse response) throws Exception {
System.out.println("hi welcome to callback method");
OAuthService oAuthService = facebookServiceProvider.getService();
Verifier verifier = new Verifier(code);
Token accessToken = oAuthService
.getAccessToken(Token.empty(), verifier);
// Token accessToken = new Token("EAADOe1JXBWgBAJVtLpGKTM6pol0n8r8fZAHnEPmNZCnId9419k9EHj2scdtcZBotMW5oYneKTvY93ZASRpeUGLiXRKhWvuZBA3zfEgIjGpvLMZCzODvA3SuNm9glARg0c5puZARVuTyZAiSqibD76taIUk06O08lOSm2vJDufCAlUdIP8P9c4ZBLP", "", "");
System.out.println("accessToken "+accessToken);
FacebookTemplate template = new FacebookTemplate(accessToken.getToken());
System.out.println(template.isAuthorized()+" autherized or not condition");
FacebookProfile facebookProfile = template.userOperations()
.getUserProfile();
System.out.println("user permissions "+template.userOperations().getUserPermissions());
String userId = facebookProfile.getId();
System.out.println("user about "+facebookProfile.getAbout());
LOGGER.info("Logged in User Id : {}", userId);
MultiValueMap<String, Object> map = facebookUtil
.publishLinkWithVisiblityRestriction(state);
try {
template.publish(facebookProfile.getId(), "feed", map);
} catch (Exception ex) {
LOGGER.error(
"Exception Occurred while posting a link on facebook for user Id : {}, exception is : {}",
userId, ex);
return PUBLISH_ERROR;
}
return PUBLISH_SUCCESS;
}
In above method i am getting all parameters (like email, first name, about etc) as null
Please follow the instructions below:
https://www.petrikainulainen.net/programming/spring-framework/adding-social-sign-in-to-a-spring-mvc-web-application-registration-and-login/
My Java Restful service login method returns a JSONObject (with name, username, and so on) in a ResponseBuilder entity. I'm trying to get it inside an AsyncHttpResponseHandler (using loopj) in my Android app. The problem is: the onSuccess method expecting a byte[] response, not a JSONObject. How to get the JSONObject inside onSuccess method in order to use it's values (user data) on my app?
Here is my code:
My Restful API login method
public Response login(#Context HttpHeaders httpHeaders,
#FormParam("username") String username,
#FormParam("password") String password) {
Authenticator authenticator = Authenticator.getInstance();
String serviceKey = httpHeaders
.getHeaderString(HTTPHeaderNames.SERVICE_KEY);
try {
// My login method returns an JSONObject with data of the logged user
JSONObject obj = authenticator
.login(serviceKey, username, password);
return getNoCacheResponseBuilder(Response.Status.OK).entity(obj)
.build();
} catch (final LoginException ex) {
return getNoCacheResponseBuilder(Response.Status.UNAUTHORIZED)
.entity(ex.getMessage()).build();
}
}
Login method on my app:
private void loginTask(RequestParams params){
AppRestClient.post("access/login", params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
// Here I want to get the JSONObject, but response is
// returning something like [B#653abba
Log.d(TAG, response);
}
...
}
Should I transform byte[] into JSONObject (if yes, how can I do that?) or should I change my ResponseBuilder entity to return something different than a JSONObject?
I already tried to use the JsonHttpResponseHandler class but the response is empty.
I'm trying to send data to jsp but its not working
public class LoginPageController extends SimpleFormController
{
public ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws ServletException
{
Loginpage lcmd=(Loginpage)command;
System.out.println("This is LOGIN PAGE");
System.out.println(lcmd.getUserName());
System.out.println(lcmd.getPassWord());
request.setAttribute("MSG","Thank u"); //This code not doing anything.
return new ModelAndView(new RedirectView("Login.jlc"));
}
}
You are changing the request object, that will indeed do nothing.
What you want is add a variable to the Model. So here's how you can do it:
Instead of:
request.setAttribute("MSG","Thank u"); //This code not doing anything.
return new ModelAndView(new RedirectView("Login.jlc"));
Try this:
Map<String, Object> model = new HashMap<String, Object>();
model.put("MSG", "Thank u");
return new ModelAndView(new RedirectView("Login.jlc"), model); // <-- notice this
This will enable you to access that "Thank u" value through the expression ${model.MSG} and others, if you add them to the model map.