How to do an HTTP Post in Android to web api - java

I am trying to do a post to web api from android. The below is the code that I am using in android. The code is running without exception however the data is not inserted to the database. I included the code that I am using.
#Override
protected List doInBackground(Void... params)
{
List userDetails3 = new ArrayList();
URL url = null;
String urlshared = "http://10.0.0.9/MyWebApi/api/Student/PostAddStudent?userName="+"s4"+"&"+"password="+"1234"+"&"+"firsName="+"z"+"&"+"lastName="+"g"+"&"+"telephone="+"9160000000"+"&"+"address="+"2300 xxx"+"&"+"aliasMailId="+"s1.xx"+"&"+"emailId="+"xx#gmail.com"+"&"+"skypeId="+"z.g"+"";
try {
url = new URL(urlshared);
}
catch (MalformedURLException exception)
{
exception.printStackTrace();
}
HttpURLConnection httpURLConnection = null;
DataOutputStream dataOutputStream = null;
try
{
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpURLConnection.setRequestMethod("POST");
PrintWriter out = new PrintWriter(httpURLConnection.getOutputStream()); // this code is executed without exception
}
catch (IOException exception)
{
exception.printStackTrace();
}
return userDetails3; // (in debug) the code will run successfuly till here without exception
}
I am trying to access the PostAddStudent in the webapi. The below is my implementation of the controller and I excluded the codes inside the methods. For your information, I did test "PostAddStudent" and the other methods in the RegisterController by using the postman and they are working fine and the data inserted to database.
public class RegisterController : ApiController
{
public IEnumerable<Register> GetRegisterAuth(string userName,string password)
{
//return instance of register
}
public IEnumerable<Register> GetRegisterByUserName(string userName)
{
//return instance of register
}
public HttpResponseMessage PostAddInstructor(string instUserName, string instPassword, string instFirsName, string instLastName, string instTelephone, string instAddress, string instAliasMailId, string instEmailId, string instSkypeId)
{
//add to database and if okay will return System.Net.HttpStatusCode.Created
var response = Request.CreateResponse<Instructor>(System.Net.HttpStatusCode.Created, inst);
//if error exist then just return Badrequest
var response = Request.CreateResponse<Instructor>(System.Net.HttpStatusCode.BadRequest, inst);
}
public HttpResponseMessage PostAddStudent(string userName, string password, string firsName, string lastName, string telephone, string address, string aliasMailId, string emailId, string skypeId)
{
//add to database and if okay will return System.Net.HttpStatusCode.Created
var response = Request.CreateResponse<Instructor>(System.Net.HttpStatusCode.Created, inst);
//if error exist then just return Badrequest
var response = Request.CreateResponse<Instructor>(System.Net.HttpStatusCode.BadRequest, inst);
}
}
the below is the RouteConfig
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
//config.EnableSystemDiagnosticsTracing();
}
}
the below is the WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
I need the android code that can do the post to PostAddStudent.
thanks

Related

in Opentelemetry, not able to get parent span

I am new to OpenTelemetry word. I have created spans for my services separately, but when i am try to combine spans of two different services, using context propogation, I am not able to do it successfully.
I have used following code:
// at client side:
public static void sendContext(String resource) {
TextMapSetter<HttpURLConnection> setter =
new TextMapSetter<HttpURLConnection>() {
#Override
public void set(HttpURLConnection carrier, String key, String value) {
carrier.setRequestProperty(key, value);
}
};
HttpURLConnection transportLayer = null;
String urlString = "http://127.0.0.1:8080" + resource;
try {
URL url = new URL(urlString);
transportLayer = (HttpURLConnection) url.openConnection();
} catch (MalformedURLException ex) {
System.out.println(ex.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
GlobalOpenTelemetry.getPropagators()
.getTextMapPropagator()
.inject(Context.current(), transportLayer, setter);
}
// at server side:
public static Context getContext(HttpServletRequest request) {
TextMapGetter<HttpServletRequest> getter =
new TextMapGetter<HttpServletRequest>() {
#Override
public String get(HttpServletRequest carrier, String key) {
Enumeration<String> headerNames = carrier.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
System.out.println("headerNames.nextElement(): " + headerName);
if (headerName.equals(key)) {
String headerValue = request.getHeader(headerName);
System.out.println("headerValue): " + headerValue);
return headerValue;
}
}
}
return null;
}
#Override
public Iterable<String> keys(HttpServletRequest carrier) {
Set<String> set = new HashSet<String>();
Enumeration<String> headerNames = carrier.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
set.add(headerNames.nextElement());
}
}
return set;
}
};
Context extractedContext =
GlobalOpenTelemetry.getPropagators()
.getTextMapPropagator()
.extract(Context.current(), request, getter);
At server, i am not able to get parent span.
Kindly help on this.
You can refer to OpenTelemetry main documentation from here. It contains the context propagation part but I used HttpHeader type getter as the TextMapGetter with the same functionality which shows in the doc and instead of using
Scope scope = extractedContext.makeCurrent()
as the scope to create a child span, better to use directly without the scope,
tracer.spanBuilder(spanName).setParent(extractedContext)
Because sometimes the automated way to propagate the parent span on the current thread does not work fine.

POST doesn't create object in Java

I am trying to develop a RESTful application that allows the client to add users to a database. This is the User class
public class User {
private String id;
private String name;
public User(String id, String name){
this.id = id;
this.name = name;
}
//------------Getters and setters-----------------------------------------------------
public String getId(){
return id;
}
public String getName(){
return name;
}
}
this is the User database class
public class UserDatabase {
private Map<String, String> users = new HashMap<String, String>();
public UserDatabase(){
users.put("2", "User2");
users.put("3", "User3");
}
public Map<String, String> getAllUsers(){
return users;
}
public String getUserName(String id){
return users.get(id);
}
public void addUser(String id, String name){
users.put(id, name);
}
}
this is the User resource
#Path("/users")
public class UserResource {
UserDatabase usersDatabase = new UserDatabase();
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_JSON)
public String getUser(#PathParam("id") String id){
String response = String.valueOf(usersDatabase.getAllUsers().size());
return response + " " + usersDatabase.getUserName(id);
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response addUser(String userString) throws JSONException {
JSONObject user = new JSONObject(userString);
String userId = user.getString("id");
String userName = user.getString("name");
usersDatabase.addUser(userId, userName);
String result = "Created user with id: " + userId + " and name: " + usersDatabase.getUserName(userId);
return Response.status(201).entity(result).build();
}
}
And this is the client with which i make a POST request to add a new user and then a GET request to get the user i just added
public class TestClient {
private final String baseUrl = "http://localhost:8080/BoardGameManager/rest";
public static void main(String[] args) throws IOException{
TestClient client = new TestClient();
client.sendPostRequest("/users");
client.sendGetRequest("/users/1");
}
private void sendGetRequest(String urlString) throws IOException{
//Building and sending GET request
URL url = new URL(baseUrl+ urlString);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
System.out.println("Sending get request : "+ url);
System.out.println("Response code : "+ responseCode);
//Reading response from input Stream
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String output;
StringBuffer response = new StringBuffer();
while ((output = in.readLine()) != null){
response.append(output);
}
in.close();
//printing result from response
System.out.println(response.toString());
}
private void sendPostRequest(String urlString) throws IOException {
//Building POST request
URL url = new URL(baseUrl + urlString);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type","application/json");
String postData = "{\"id\": \"1\",\"name\": \"User1\"}";
//Sending POST request
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(postData);
outputStream.flush();
outputStream.close();
//Receiving response
int responseCode = connection.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post Data : " + postData);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String output;
StringBuffer response = new StringBuffer();
while ((output = in.readLine()) != null) {
response.append(output);
}
in.close();
//printing result from response
System.out.println(response.toString());
}
}
The problem is that when i make the POST request the user is added, but when I try to get it with the GET request the user i just added doesn't exist, and I can't understand why this happens.
Actually you are instantiating userDatabases as new UserDatabase() so everytime you get a new copy of userDatabases hence you get everytime a new users Map.
I propose to make your UserDatabasea singleton instead to keep every new added user to the Map:
public class UserDatabase {
private static UserDatabase instance = null;
public static UserDatabase getInstance() {
if(instance == null) {
instance = new UserDatabase();
}
return instance;
}
private UserDatabase(){
users.put("2", "User2");
users.put("3", "User3");
}
//....
}
Then instantiate UserDatabase like this :
#Path("/users")
public class UserResource {
UserDatabase usersDatabase = UserDatabase.getInstance();
}
Now everytime you call UserDatabase.getInstance() you will get the same copy of it hence the same users Map.
Actually you don't even have to implement singleton pattern here if you are using spring boot to develop your micro service. You can use #Service annotation on your UserDatabase class. Then in your UserResource class do the following.
#Autowired
UserDatabase usersDatabase = new UserDatabase();
Spring will manage singleton instances here on behalf of you.
Following dependencies would be enough. But I reckon you to create a project using spring initializer by adding dependencies as needed. The default dependencies as given below would be sufficient as I remember. Additionally you may find a sample project here.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

Identifying the current user requesting the rest endpoints

I am trying to implement authentication and authorization using angular and java where I came across "identifying the current user asking for resource" from this Link
The point where I am not able to understand is getting the user from getUserPrincipal() method using jax-rs SecurityContext.
Security Context:
requestContext.setSecurityContext(new SecurityContext() {
#Override
public Principal getUserPrincipal() {
return new Principal() {
#Override
public String getName() {
return email;
}
};
}
}
The above method apparently returns a user but the question is from where? I have searched on this topic but no where I see code for fetching the user from DB or any other resource.
Where as I have implemented some thing like this for validation:
#Secured
#Provider
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Get the HTTP Authorization header from the request
String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// Check if the HTTP Authorization header is present and formatted correctly
if (authorizationHeader == null || !authorizationHeader.startsWith("Basic ")) {
throw new NotAuthorizedException("Authorization header must be provided");
}
// Extract the token and email address from the HTTP Authorization header
String email = requestContext.getHeaderString("Email");
String token = authorizationHeader.substring("Basic".length()).trim();
try {
// Validate the token
validateToken(email, token);
} catch (Exception e) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
private void validateToken(String email, String token) throws Exception {
// Check if it was issued by the server and if it's not expired
// Throw an Exception if the token is invalid
try {
TokenSaverAndValidatorDAO tokenValidator = new TokenSaverAndValidatorDAO();
String result = tokenValidator.checkTokenFromDB(email, token);
if (result.equals(token)) {
System.out.println("Token is same");
} else {
System.out.println("Token is not same");
throw new Exception();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
The above method validateToken() calls a method from DAO class for validation:
public String checkTokenFromDB(String email, String token) {
String result = "";
try {
String query = "Select USR_TOKEN From TBL_USER where USR_PRIMARY_EMAIL= ? ";
Connection con = DBConnection.getConnection();
PreparedStatement statement = con.prepareStatement(query);
statement.setString(1, email);
ResultSet rs = statement.executeQuery();
while (rs.next()) {
result = rs.getString("USR_TOKEN");
}
} catch (Exception ex) {
System.out.println("Error in TokenSaverDAO class");
ex.printStackTrace();
}
return result;
}
How do I use jax-rs securityContext in my application. Does it apply to my scenario?
I am sending the headers from angular like this:
$httpProvider.interceptors.push(['$q', '$location', '$localStorage', 'jwtHelper', function ($q, $location, $localStorage, jwtHelper) {
return {
'request': function (config) {
config.headers = config.headers || {};
if ($localStorage.token) {
var decodeToken = jwtHelper.decodeToken($localStorage.token);
config.headers.Email = decodeToken.email;
config.headers.Authorization = 'Basic ' + $localStorage.token;
}
return config;
},
'responseError': function (response) {
if (response.status === 401 || response.status === 403) {
$location.path('/Login');
}
return $q.reject(response);
}
};
}]);
Where the headers are set like this:
config.headers.Email = decodeToken.email;
config.headers.Authorization = 'Basic ' + $localStorage.token;

Unable to store / retrieve cookie in a spring-boot application

In my current spring-boot project, I add this class with the goal to allow me store and retrieve cookies:
public class CookieAcessor {
public static List<HttpCookie> getCookies() {
try {
CookieManager manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);
CookieStore cookieJar = manager.getCookieStore();
URL url = new URL("http://localhost:8080");
List <HttpCookie> cookies = cookieJar.get(url.toURI());
return cookies;
} catch(Exception e) {
return new ArrayList<HttpCookie>();
}
}
public static String getCookie(String key) {
List<HttpCookie> cookies = getCookies();
for(HttpCookie cookie : cookies) {
if(cookie.getName().equals(key))
return cookie.getValue();
}
return null;
}
public static void setCookie(String key, String value) {
try {
CookieManager manager = new CookieManager();
CookieHandler.setDefault(manager);
CookieStore cookieJar = manager.getCookieStore();
HttpCookie cookie = new HttpCookie(key, value);
URL url = new URL("http://localhost:8080");
cookieJar.add(url.toURI(), cookie);
} catch(Exception e) {
System.out.println("Erro ao armazenar o cookie!");
}
}
}
but when I try execute any methods from this class (for read or save a cookie), nothing is done. Anyone can see what's wrong with this code? It was based on this article from official documentation: http://docs.oracle.com/javase/tutorial/deployment/doingMoreWithRIA/accessingCookies.html.
UPDATE
this class is used in a method from controller like this:
#RequestMapping(value = "/")
public String index() {
CookieAcessor.setCookie("teste", "...");
System.out.println("cookie[teste] = "+CookieAcessor.getCookie("teste"));
return "public/index";
}

Gson - attempting to convert json string to custom object

Here is my Json returned from the server
{"ErrorCode":1005,"Message":"Username does not exist"}
Here is my class for an error
public class ErrorModel {
public int ErrorCode;
public String Message;
}
and here is my conversion code.
public static ErrorModel GetError(String json) {
Gson gson = new Gson();
try
{
ErrorModel err = gson.fromJson(json, ErrorModel.class);
return err;
}
catch(JsonSyntaxException ex)
{
return null;
}
}
It is always throwing a JsonSyntaxException. Any ideas what could be my problem here?
EDIT: As requested, here is further elaboration.
My backend is an ASP.NET MVC 2 application acting as a rest API. The backend isn't the problem here, as my actions (and even server errors) all return Json (using the built in JsonResult). Here's a sample.
[HttpPost]
public JsonResult Authenticate(AuthenticateRequest request)
{
var authResult = mobileService.Authenticate(request.Username, request.Password, request.AdminPassword);
switch (authResult.Result)
{
//logic omitted for clarity
default:
return ExceptionResult(ErrorCode.InvalidCredentials, "Invalid username/password");
break;
}
var user = authResult.User;
string token = SessionHelper.GenerateToken(user.UserId, user.Username);
var result = new AuthenticateResult()
{
Token = token
};
return Json(result, JsonRequestBehavior.DenyGet);
}
The basic logic is to auth the user cretentials and either return an ExceptionModel as json or an AuthenticationResult as json.
Here is my server side Exception Model
public class ExceptionModel
{
public int ErrorCode { get; set; }
public string Message { get; set; }
public ExceptionModel() : this(null)
{
}
public ExceptionModel(Exception exception)
{
ErrorCode = 500;
Message = "An unknown error ocurred";
if (exception != null)
{
if (exception is HttpException)
ErrorCode = ((HttpException)exception).ErrorCode;
Message = exception.Message;
}
}
public ExceptionModel(int errorCode, string message)
{
ErrorCode = errorCode;
Message = message;
}
}
When the above authentication is called with invalid credentials, the error result is returned as expected. The Json returned is the Json above in the question.
On the android side, I first build an object with my key-value pairs.
public static HashMap<String, String> GetAuthenticationModel(String username, String password, String adminPassword, String abbr)
{
HashMap<String, String> request = new HashMap<String, String>();
request.put("SiteAbbreviation", abbr);
request.put("Username", username);
request.put("Password", password);
request.put("AdminPassword", adminPassword);
return request;
}
Then, I send off an http post and return as a string whatever is sent back.
public static String Post(ServiceAction action, Map<String, String> values) throws IOException {
String serviceUrl = GetServiceUrl(action);
URL url = new URL(serviceUrl);
URLConnection connection = url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String data = GetPairsAsString(values);
DataOutputStream output = new DataOutputStream(connection.getOutputStream());
output.writeBytes(data);
output.flush();
output.close();
DataInputStream input = new DataInputStream(connection.getInputStream());
String line;
String result = "";
while (null != ((line = input.readLine())))
{
result += line;
}
input.close ();
return result;
}
private static String GetServiceUrl(ServiceAction action)
{
return "http://192.168.1.5:33333" + action.toString();
}
private static String GetPairsAsString(Map<String, String> values){
String result = "";
Iterator<Entry<String, String>> iter = values.entrySet().iterator();
while(iter.hasNext()){
Map.Entry<String, String> pairs = (Map.Entry<String, String>)iter.next();
result += "&" + pairs.getKey() + "=" + pairs.getValue();
}
//remove the first &
return result.substring(1);
}
Then I take that result and pass it into my parser to see if it is an error
public static ErrorModel GetError(String json) {
Gson gson = new Gson();
try
{
ErrorModel err = gson.fromJson(json, ErrorModel.class);
return err;
}
catch(JsonSyntaxException ex)
{
return null;
}
}
But, JsonSyntaxException is always thrown.
Might help to know more about the exception, but the same code sample works fine here. I suspect there's a piece of code you omitted that's causing the problem (perhaps the creation/retrieval of the JSON string). Here's a code sample that worked fine for me on Java 1.6 and Gson 1.6:
import com.google.gson.Gson;
public class ErrorModel {
public int ErrorCode;
public String Message;
public static void main(String[] args) {
String json = "{\"ErrorCode\":1005,\"Message\":\"Username does not exist\"}";
Gson gson = new Gson();
ErrorModel err = gson.fromJson(json, ErrorModel.class);
System.out.println(err.ErrorCode);
System.out.println(err.Message);
}
}

Categories