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>
Related
I really need help here, im Deserializing the next json:
{
"name":"myname",
"userID":"12345",
"password":"sha1passwordASDESFSGSD",
"active":"1",
"profile":"2",
"job":"Manager"
}
Im using Jersey to create webService, when i recive the json i recive it as a InputStream
Also i tried with a String
#POST
#Path("user/in/")
#Produces("application/json")
public String InsertUser(InputStream inStr)
{
String line = null, res = "POST 200 > ";
BufferedReader br = new BufferedReader(new InputStreamReader(inStr));
try {
while ((line = br.readLine()) != null) {
System.out.println(line);
res += line;
}
} catch (IOException e) {
e.printStackTrace();
}
try {
UserInformation user = new Gson().fromJson(res, UserInformation.class);
System.out.println("All done");
System.out.println(user.getName());
} catch (Exception e) {
System.out.println("Error al convertir jo object " + e.getCause() + e.getMessage());
}
return "POST 200 > ";
}
I tried using a InputStreamReader:
#POST
#Path("user/in/")
#Produces("application/json")
public String InsertUser(InputStream inStr)
{
try {
InputStreamReader isr = new InputStreamReader(inStr);
UserInformation user = new Gson().fromJson(isr, UserInformation.class);
System.out.println("All done");
System.out.println(user.getName());
} catch (Exception e) {
System.out.println("Error al convertir jo object " + e.getCause() + e.getMessage());
}
return "POST 200 > ";
}
Neither of those codes work. They don't throw an exception or print "All done".
When i debug the object, user doesn't appear in the variables menu.
In my experience, is because an error is happening in the line UserInformation user = new Gson().fromJson(isr, UserInformation.class);
But i cant see which one is.
My UserInformation Class is the next
public class UserInformation {
private String name;
private String userID;
private String password;
private String active;
private String profile;
private String job;
// Methods removed for brevity
}
I am assuming you are using Google gson. Here is my answer:
#Post
#Path("user/in")
#Produces(MediaType.APPLICATION_JSON)
public Response InsertUser(string json){
JsonElement jsonElement = new JsonParser().parse(json);
JsonObject object = jsonElement.getAsJsonObject();
String name = object.getAsJsonPrimitive("name").getAsString();
int userID = object.getAsJsonPrimitve("userID").getAsInt();
String password = object.getAsJsonPrimitive("password").getAsString();
String job = object.getAsJsonPrimitive("job").getAsString();
int active = object.getAsJsonPrimitve("active").getAsInt();
int profile = object.getAsJsonPrimitve("profile").getAsInt();
return Response.status(Response.Status.OK).entity("all done").build();
}
I already find the solution, the problem was that i was receiving a InputStream,
following its recommendations the solution code is:
#POST
#Path("users/in/")
#Produces(MediaType.APPLICATION_JSON)
public String InsertUser(String json)
{
try{
UserInformation user = new Gson().fromJson(json, UserInformation.class);
String name = user.getName();
String userID = user.getUserID();
String password = user.getPassword();
String job = user.getJob();
String active = user.getActive();
String profile = user.getProfile();
}catch(Exception e){
System.out.println(Response.status(500).entity(e.getCause() + e.getMessage()).build().toString());
return Response.status(500).entity(e.getCause() + e.getMessage()).build().toString();
}
}
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
Just started making a program to upload data into a smartsheet. Problem is i am getting the error "Invalid Accept header. Media type not supported. " its happening here
connection = (HttpURLConnection) new URL(GET_SHEETS_URL).openConnection();
connection.addRequestProperty("Authorization", "Bearer " + accessToken);
here is what i have taken from smartsheet github
public class JavaSDKSample {
private static final String BASE_URL = "https://api.smartsheet.com/2.0";
private static final String GET_SHEETS_URL = BASE_URL + "/sheets";
private static final String SHEET_ID = "{sheetId}";
private static final String SHARE_SHEET_URL = BASE_URL + "/sheet/" + SHEET_ID + "/shares";
public static void main(String[] args) {
HttpURLConnection connection = null;
StringBuilder response = new StringBuilder();
//We are using Jackson JSON parser to deserialize the JSON. See http://wiki.fasterxml.com/JacksonHome
//Feel free to use which ever library you prefer.
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
System.out.println("STARTING HelloSmartsheet...");
//Create a BufferedReader to read user input.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter Smartsheet API access token:");
String accessToken = in.readLine();
System.out.println("Fetching list of your sheets...");
//Create a connection and fetch the list of sheets
connection = (HttpURLConnection) new URL(GET_SHEETS_URL).openConnection();
connection.addRequestProperty("Authorization", "Bearer " + accessToken);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
//Read the response line by line.
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
//Use Jackson to convert the JSON string to a List of Sheets
List<Sheet> sheets
= mapper.readValue(response.toString(), new TypeReference<List<Sheet>>() {});
if (sheets.size() == 0) {
System.out.println("You don't have any sheets. Goodbye!");
return;
}
System.out.println("Total sheets: " + sheets.size());
int i = 1;
for (Sheet sheet : sheets) {
System.out.println( i++ + ": " + sheet.name);
}
System.out.print("Enter the number of the sheet you want to share: ");
//Prompt the user to provide the sheet number, the email address, and the access level
Integer sheetNumber = Integer.parseInt(in.readLine().trim()); //NOTE: for simplicity, error handling and input validation is neglected.
Sheet chosenSheet = sheets.get(sheetNumber - 1);
System.out.print("Enter an email address to share " + chosenSheet.getName() + " to: ");
String email = in.readLine();
System.out.print("Choose an access level (VIEWER, EDITOR, EDITOR_SHARE, ADMIN) for " + email + ": " );
String accessLevel = in.readLine();
//Create a share object
Share share = new Share();
share.setEmail(email);
share.setAccessLevel(accessLevel);
System.out.println("Sharing " + chosenSheet.name + " to " + email + " as " + accessLevel + ".");
//Create a connection. Note the SHARE_SHEET_URL uses /sheet as opposed to /sheets (with an 's')
connection = (HttpURLConnection) new URL(SHARE_SHEET_URL.replace(SHEET_ID, "" + chosenSheet.getId())).openConnection();
connection.setDoOutput(true);
connection.addRequestProperty("Authorization", "Bearer " + accessToken);
connection.addRequestProperty("Content-Type", "application/json");
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
//Serialize the Share object
writer.write(mapper.writeValueAsString(share));
writer.close();
//Read the response and parse the JSON
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
Result result = mapper.readValue(response.toString(), Result.class);
System.out.println("Sheet shared successfully, share ID " + result.result.id);
System.out.println("Press any key to quit.");
in.read();
} catch (IOException e) {
BufferedReader reader = new BufferedReader(new InputStreamReader(((HttpURLConnection) connection).getErrorStream()));
String line;
try {
response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
Result result = mapper.readValue(response.toString(), Result.class);
System.out.println(result.message);
} catch (IOException e1) {
e1.printStackTrace();
}
} catch (Exception e) {
System.out.println("Something broke: " + e.getMessage());
e.printStackTrace();
}
}
public static class Sheet {
Long id;
String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static class Share {
String email;
String accessLevel;
Long id;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAccessLevel() {
return accessLevel;
}
public void setAccessLevel(String accessLevel) {
this.accessLevel = accessLevel;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
public static class Result {
String message;
Share result;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Share getResult() {
return result;
}
public void setResult(Share result) {
this.result = result;
}
}
}
The error message Invalid Accept header is your clue. You need to set the appropriate Accept header, in this case application/json.
Add the following line just below the line where you set your connection variable.
connection.setRequestProperty("Accept", "application/json");
Also, you may be interested in using the existing SDKs that are available for Smartsheet, listed here.
I want to send the input as json using the HttpURLConnection in java client and the request will be handled by the Spring MVC library jacksonhaus to response the output as json
URL url = new URL("http://www.test.com/SpringMVC/rest/service/getEmpDetails");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
String input = "{\"name\":\"emp1\",\"add\":\"emp2\"}";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
When i use this code i am getting
HTTP error code : 500
In Spring MVC am using the model Attribute for the input Request. Can anyone help me on this.
Not sure about your controller code are you sending http_created from controller? should you be looking for HttpURLConnection.HTTP_OK.
Below code may help you
Controller code:
#RequestMapping(value="/jsonconsumer", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody String consumer(#RequestBody JavaBean javaBean) {
return "created";
}
JavaBean code:
#XmlRootElement
public class JavaBean {
private String name = "";
private String add = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
#Override
public String toString() {
return "JavaBean {name=[" + name + "], add=[" + add + "]}";
}
}
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);
}
}