I tried a sample for post requests in IBM MF8 Java adapter.
Inside this adapter, I am trying to to call another Java adapter, SampleAdapter and want to do a POST with userDetails as parameter
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("/balanced")
#OAuthSecurity(enabled = false)
public JSONObject generate(UserDetails userDetails , HttpRequest request, HttpSession session) throws UnsupportedEncodingException {
String messages = null;
String getProcedureURL = "/SampleAdapter/resource";
StringEntity requestEntity = new StringEntity(userDetails.toString(),ContentType.APPLICATION_JSON);
HttpPost httpPost = new HttpPost(getProcedureURL);
httpPost.setEntity(requestEntity);
JSONObject jsonObj = null;
HttpResponse response;
try {
response = adaptersAPI.executeAdapterRequest(httpPost);
jsonObj = adaptersAPI.getResponseAsJSON(response);
messages = (String)jsonObj.get("subscriptionMessage");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONObject json = new JSONObject();
json.put("value", messages);
return json;
}
SampleAdapter has to get the object userDetails. So that I can use it in the back end for some operations.
But, here I am unable to get the data into SampleAdapter. Also, I tried returning some String from SampleAdapter.
I get the below error
{"responseText":"","error":"Response cannot be parsed to JSON"}
I know that IBM MF does the json conversion internally, but here how is it possible to do a POST from one adapter to adapter.
I see samples given only for GET requests.
Any suggestions to do for POST?
I wrote you a short example based on yours:
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("/balanced")
#OAuthSecurity(enabled = false)
public JSONObject generate() throws UnsupportedEncodingException {
String messages = null;
String getProcedureURL = "/SampleAdapter/resource/hello";
StringEntity requestEntity = new StringEntity("world", ContentType.APPLICATION_JSON);
HttpPost httpPost = new HttpPost(getProcedureURL);
httpPost.setEntity(requestEntity);
JSONObject jsonObj = null;
HttpResponse response;
try {
response = adaptersAPI.executeAdapterRequest(httpPost);
jsonObj = adaptersAPI.getResponseAsJSON(response);
messages = "Hello " + (String)jsonObj.get("name");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONObject json = new JSONObject();
json.put("value", messages);
return json;
}
And here is the POST endpoint:
#POST
#Produces(MediaType.APPLICATION_JSON)
#Path("/hello")
#OAuthSecurity(enabled = false)
public Map<String, String> hello(String name) {
Map<String, String> result = new HashMap<String, String>();
result.put("name", name);
return result;
}
I hope this will help you.
Related
I wrote both Service and CLient part of application. I tested my service with "Postman" application and it is working fine with url = http://192.168.2.50:8084/FaceBusinessService/webresources/service/login?phone=123456789&password=1234
However when I try to call it on my Android Application it is not working. While debuging on service side I see that phone and password parameters are NULL.
Here is my service side :
#Path("login")
#POST
#Produces("application/json")
public String postJson(#QueryParam("phone")String phone, #QueryParam("password") String password) {
String info = null;
try {
UserInfo userInfo = null;
UserModel userModel = new UserModel();
userInfo = userModel.isPersonRegistered(phone, password);
Gson gson = new Gson();
System.out.println(gson.toJson(userInfo));
info = gson.toJson(userInfo);
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
return info;
}
Here is my android app side :
private UserInfo loginUser(String phone, String password) {
UserInfo userInfo = null;
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost("http://192.168.2.27:8084/FaceBusinessService/webresources/service/login");
try {
/*
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("phone", new StringBody(phone));
entity.addPart("password", new StringBody(password));
post.setEntity(entity);
*/
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("phone", phone));
params.add(new BasicNameValuePair("password", password));
post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
Log.d(TAG, "POST String: " + post.toString());
try {
HttpResponse response = httpClient.execute(post);
if (response.getEntity().getContentLength() > 0) {
String json_string = EntityUtils.toString(response.getEntity());
JSONObject jsonObject = new JSONObject(json_string);
// TODO
return userInfo;
}
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
return null;
}
I tried both MultipartEntity and NameValuePair but none of them worked. Could you give me idea how to handle this issue?
Note that when testing with Postman you passed parameters (user name and password) as part of the URL (URL encoded), which can be directly retrieved on the server side. (you don't even need a POST request for this). Your objects are passed as string objects, not JSON objects.
In your client code , the URL is different because you're encoding the parameters as part of the POST request entity (payload). The parameters are packaged inside of the request/message body and not in the URL.
Now since your URL doesn't have the parameters, you should retrieve them by deserializing the request (desderialize the JSON request into a UserInfo object).
Note that you should rewrite your server side code completely as it should accept a application/JSON object but it apparently should return/produce a String object (plain/text or application/HTML).
I'm not familiar with GSON but your code might look something like
#Path("login")
#POST
#Produces("text/plain")
#Consumes("application/json")
public String postJson(UserInfo ui) {
String info = null;
try {
UserInfo userInfo = null;
UserModel userModel = new UserModel();
userInfo = userModel.isPersonRegistered(ui.phone, ui.password);
Gson gson = new Gson();
System.out.println(gson.toJson(userInfo));
info = gson.toJson(userInfo);
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
return info;
}
I am struggling in finding a replacement for the deprecated DefaultHttpClient and connected classes liken HttpPost etc.
In a first attempt, I tried using the volley library, but nothing seemed to work, so after a bit research I am trying now with Retrofit 1.9.
In my app, I connect to a own restful client. Here is the old code (example POST), which works perfectly well:
private static DefaultHttpClient httpClient = new DefaultHttpClient();
public static String executePOST(Map<String, String> postParams, int connTO, int sockTO, String uri){
String res, message;
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, connTO);
HttpConnectionParams.setSoTimeout(httpParams, sockTO);
HttpConnectionParams.setTcpNoDelay(httpParams, true);
httpClient.setParams(httpParams);
HttpPost httppost = new HttpPost(uri);
JSONObject json = new JSONObject();
try {
Iterator<Entry<String, String>> iterator = postParams.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String, String> pair = (Map.Entry<String, String>)iterator.next();
json.put(pair.getKey(), pair.getValue());
}
message = json.toString();
httppost.setEntity(new StringEntity(message, "UTF8"));
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(httppost);
HttpEntity entity = response.getEntity();
res = EntityUtils.toString(entity).trim();
} catch (ClientProtocolException e) {
res = "Client Protocol Exception";
} catch (IOException e) {
res = e.getLocalizedMessage();
} catch (JSONException e){
res = e.getLocalizedMessage();
}
return res;
}
I send the request like this from my Activity
Map<String, String> arguments = new HashMap<String, String>();
arguments.put("email", username);
new HttpClient(arguments, new LoginActivityCommunicationListener(this, LoginOperation.EMAIL_CHECK), URI_ROOT + "/kunde", 0).execute();
The listener in the arguments handles the response callback, the 0 means POST.
this results in a JSON response, having the fields id and person
So I tried to implement a Retrofit variant of above like this
MyApi.java
public interface MyDosAPI {
#FormUrlEncoded
#POST("/kunde")
public void checkEmail(#Field("email") String email, Callback<EmailCheck> response);
}
EmailCheck.java
public class EmailCheck {
#SerializedName("id")
private String id;
#SerializedName("person")
private String person;
public void setId(String id){
this.id = id;
}
public void setPerson(String person){
this.person = person;
}
public String getId(){
return id;
}
public String getPerson(){
return person;
}
}
and in the activity
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(URI_ROOT)
.build();
MyDosAPI api = adapter.create(MyDosAPI.class);
api.checkEmail(username, new Callback<EmailCheck>() {
#Override
public void success(EmailCheck emailChecks, Response response) {
Log.i("MyCount", "success");
}
#Override
public void failure(RetrofitError error) {
Log.i("MyCount", error.getMessage());
}
});
result
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
obviously there is something essential that I am missing. Is there - apart of Retrofit or Volley - another solution where I can define the requests like I did before?
Change to:
public interface MyDosAPI {
#POST("/kunde")
public void checkEmail(#Body String email, Callback<EmailCheck> response);
}
Right Now I have a Restful Web service called Users.java, That fake adds a user to a fake database
#Path("/users")
public class UsersService {
#POST
public Response handlePost(String requestBody) {
addUserToDatabase(requestBody);
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("status", "success");
jsonMap.put("resource-uri", "/users/12"); // assume 12 is the ID of the user we pretended to create
Gson gson = new Gson();
return Response.status(200).entity(gson.toJson(jsonMap)).build();
}
private boolean addUserToDatabase(String requestBody) {
Gson gson = new Gson();
Map<String, String> user = gson.fromJson(requestBody, new TypeToken<Map<String, String>>() {
}.getType());
for (String key : user.keySet()) {
System.out.println(key + ": " + user.get(key));
}
return true; // lie and say we added the user to the database
}
}
it is called using the Post request here, these are examples
public HttpResponse postRequest(String relativePath, Map<String, String> map){
try {
String fullPath = buildURL(relativePath);
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost getRequest = new HttpPost(fullPath);
Gson gson = new Gson();
String postEntity = gson.toJson(map);
getRequest.setEntity(new StringEntity(postEntity));
getRequest.addHeader("accept", "application/json");
HttpResponse response = httpClient.execute(getRequest);
httpClient.getConnectionManager().shutdown();
return response;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
// POST
Map<String, String> map = new HashMap<>();
map.put("username", "Bill");
map.put("occupation", "Student");
map.put("age", "22");
map.put("DOB", "" + new Date(System.currentTimeMillis()));
HttpResponse response = client.postRequest("/api/users", map);
client.printResponse(response);
Now I want to do something similar with Delete and Update but dont know where to start any help would be great
Use appropriate #Path, #Delete and #Putannotations and implement the methods in a similar way you did for #Post.
To post json from android to php, i used Volley library StringRequest object.
StringRequest sr = new StringRequest(Request.Method.POST,url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// some code
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//some code
}
}){
#Override
protected Map<String,String> getParams(){
Map<String, String> params = new HashMap<String, String>();
ArrayList<Command> commands = MyApplication.readFromPreferences(getActivity(), Constants.COMMAND);
String jsonCommands = new Gson().toJson(commands);
params.put("commands", jsonCommands);
return params;
}
};
And to catch the data in php and verify if it was sent correcttly, I used this
echo $_POST["commands"];
Output:
[{\"product\":{\"category_id\":1,\"created_at\":\"2015-06-13 17:49:58\",\"description\":\"CF77 COIN FINDER\",\"url_image\":\"IMG_76ECDC-707E7E-70AC81-0A1248-4675F3-F0F783.jpg\",\"name\":\"CF77 COIN FINDER\",\"pid\":12,\"price\":500.0},\"product_quantity\":3},{\"product\":{\"category_id\":1,\"created_at\":\"2015-06-13 17:49:58\",\"description\":\"JEOSONAR 3D DUAL SYSTEM\",\"url_image\":\"IMG_2D9DF0-2EB7E9-ED26C0-2C833B-B6A5C5-5C7C02.jpg\",\"name\":\"JEOSONAR 3D DUAL SYSTEM\",\"pid\":15,\"price\":500.0},\"product_quantity\":1},{\"product\":{\"category_id\":1,\"created_at\":\"2015-06-13 17:49:58\",\"description\":\"MAKRO POINTER\",\"url_image\":\"IMG_Macro.jpg\",\"name\":\"MAKRO POINTER\",\"pid\":18,\"price\":500.0},\"product_quantity\":3}]
I have noticed that when sending the json string with POST Method using Volley library, a lot of anti-slashes have been added to escape double quotes.
So here comes my problem:
I want to decode json to an array of objects in php, so i used
$commands = json_decode( $_POST["commands"],true);
But it always returns an empty array because of the invalide above json (caused by the anti-slashes).
Is there a method in php or in java SDK providing a contract for sending and receiving json without having this kind of problems? Or should i reformat the json in php and delete all the anti-slashes?
The problem is that you try to send the json data in the URL parameters.
You need to override the getBody() method to return the json data as request body, not as url parameters.
Eg:
/**
* Returns the raw POST or PUT body to be sent.
*
* #throws AuthFailureError in the event of auth failure
*/
public byte[] getBody() throws AuthFailureError {
return new Gson().toJson(commands).getBytes();
}
And then in PHP you can:
$jsonRequest = json_decode(stream_get_contents(STDIN));
first there is problem with the json itself is not build correctly is better to JSONObject for this, for example:
JSONObject js = new JSONObject();
try {
js.put("value",10);
} catch (JSONException e) {
e.printStackTrace();
}
String jss = js.toString();
you can check if the parse is success by copy the string and copy it in online parser like this http://json.parser.online.fr/
Finally, I solved my problem using a custom json_decode method in order to clean the json string before decoding it.
function json_clean_decode($json, $assoc = false, $depth = 512, $options = 0) {
// search and remove comments like /* */ and //
$json = preg_replace("#(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|([\s\t]//.*)|(^//.*)#", '', $json);
// search and remove all backslashes
$json = str_replace("\\","", $json);
if(version_compare(phpversion(), '5.4.0', '>=')) {
$json = json_decode($json, $assoc, $depth, $options);
}
elseif(version_compare(phpversion(), '5.3.0', '>=')) {
$json = json_decode($json, $assoc, $depth);
}
else {
$json = json_decode($json, $assoc);
}
return $json;
}
You can use this method to send json to web service.
public String makeServiceCallSubmit(String url, int method,
JSONArray object) {
try {
// http client
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
// Checking http request method type
if (method == POST) {
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-type", "application/json");
StringEntity se = new StringEntity(object.toString());
// se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httpPost.setEntity(se);
httpResponse = httpClient.execute(httpPost);
}
httpEntity = httpResponse.getEntity();
Response = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return Response;
}
I have a method in spring and I want to access the method using Apache HttpClient.
following is my method :
#PreAuthorize("isAuthenticated() and hasPermission(#request, 'CREATE_REQUISITION')")
#RequestMapping(method = RequestMethod.POST, value = "/trade/createrequisition")
public #ResponseBody
void createRequisition(#RequestBody CreateRequisitionRO[] request,
#RequestHeader("validateOnly") boolean validateOnly) {
logger.debug("Starting createRequisition()...");
for (int i = 0; i < request.length; i++) {
CreateRequisitionRO requisitionRequest = request[i];
// FIXME this has to be removed/moved
requisitionRequest.setFundManager(requisitionRequest.getUserId());
// FIXME might have to search using param level as well
SystemDefault sysDefault = dbFuncs.references.systemDefault
.findByCompanyAndDivisionAndPortfolio(
userContext.getCompany(),
userContext.getDivision(),
requisitionRequest.getPortfolio());
requisitionRequest.setCustodianN(sysDefault.getCustodianN());
gateKeeper.route(requisitionRequest);
}
}
And this is how I log in to the system and make the tomcat run where the application is deployed since the method uses other classes for some functionalities.
I was able to log in to the system without any issues through problematically but i get the following exception -- java.io.EOFException: No content to map to Object due to end of input
This is my main class :
package com.hexgen.reflection;
public class ReflectionWebAPITest {
public static void main(String[] args) {
HttpClientRequests httpRequest = new HttpClientRequests();
String uri="";
try {
uri = "http://localhost:8080/api/trade/createrequisition";
httpRequest.doSubmit("mayank", "hexgen",uri);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
this is my doSubmit Method :
public void doSubmit(String username, String password, String uri) {
HttpClient client = new DefaultHttpClient();
JsonConverter jsonROConverter = new JsonConverter();
CreateRequisitionRO[] request = new CreateRequisitionRO[1];
BigDecimal priceFrom= new BigDecimal("100000");
BigDecimal quantity= new BigDecimal("2");
request[0] = new CreateRequisitionRO();
request[0].setPortfolio("HEXGENFUND");
request[0].setTransSrlNo(new BigDecimal(1));
request[0].setTransCode("BUY");
request[0].setInvestReason("009");
request[0].setInflowOutflow(InflowOutflow.I);
request[0].setTradeDate(new LocalDate());
request[0].setTradeDate(new LocalDate());
request[0].setTradeDateUpto(new LocalDate());
request[0].setTradeTime("11:27:9");
request[0].setInvestCategory("FVTPL");
request[0].setCustodian("DEUTSCHE");
request[0].setHoldType("HOLD");
request[0].setSecurityType(SecurityType.INV);
request[0].setSecurity("DABU02");
request[0].setAssetClass("EQU");
request[0].setIssuer("DABU");
request[0].setMarketType(MarketType.MKT);
request[0].setTradePriceType("");
request[0].setRequisitionType(RequisitionType.SO);
request[0].setPriceFrom(priceFrom);
request[0].setPriceTo(priceFrom);
request[0].setMarketPrice(priceFrom);
request[0].setAveragePrice(priceFrom);
request[0].setPrice(priceFrom);
request[0].setQuantity(quantity);
request[0].setGrossAmtPcy(priceFrom);
request[0].setExchRate(quantity);
request[0].setGrossAmtTcy(priceFrom);
request[0].setNetAmountPcy(priceFrom);
request[0].setNetAmountTcy(priceFrom);
request[0].setAccrIntPcy(priceFrom);
request[0].setAccrIntTcy(priceFrom);
request[0].setAcquCostPcy(priceFrom);
request[0].setYieldType(YieldType.N);
request[0].setPurchaseYield(quantity);
request[0].setMarketYield(quantity);
request[0].setYtm(quantity);
request[0].setMduration(quantity);
request[0].setCurrPerNav(quantity);
request[0].setDesiredPerNav(quantity);
request[0].setCurrHolding(quantity);
request[0].setNoofDays(quantity);
request[0].setRealGlTcy(quantity);
request[0].setRealGlPcy(quantity);
request[0].setNowLater("N");
request[0].setIsAllocable(false);
request[0].setAcquCostReval(quantity);
request[0].setAcquCostHisTcy(quantity);
request[0].setAcquCostHisPcy(quantity);
request[0].setExIntPcy(quantity);
request[0].setExIntTcy(quantity);;
request[0].setAccrIntReval(quantity);
request[0].setAccrIntTcy(quantity);
request[0].setAccrIntPcy(quantity);;
request[0].setGrossAodTcy(quantity);
request[0].setGrossAodPcy(quantity);
request[0].setGrossAodReval(quantity);
request[0].setBankAccAmtAcy(quantity);
request[0].setBankAccAmtPcy(quantity);
request[0].setTaxAmountTcy(quantity);
request[0].setUnrelAmortPcy(quantity);
request[0].setUnrelAmortTcy(quantity);
request[0].setUnrelGlPcy(quantity);
request[0].setUnrelGlTcy(quantity);
request[0].setRealGlHisTcy(quantity);
request[0].setRealGlHisPcy(quantity);
request[0].setTradeFeesTcy(quantity);
request[0].setTradeFeesPcy(quantity);
boolean validateOnly = true;
HttpPost post = new HttpPost("http://localhost:8080/j_spring_security_check");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("j_username", username));
nameValuePairs.add(new BasicNameValuePair("j_password", password));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
if (entity != null) {
post.abort();
}
HttpPost postURI = new HttpPost(uri);
// Setup the request parameters
BasicHttpParams params = new BasicHttpParams();
params.setParameter("CreateRequisitionRO", jsonROConverter.serialiseRequisionRO(request));
params.setBooleanParameter("validateOnly", validateOnly);
postURI.setParams(params);
postURI.setHeader("Content-type", "application/json");
HttpResponse responseURL = client.execute(postURI);
} catch (IOException e) {
e.printStackTrace();
}
}
These are the methods which i use to convert the Java POJO to Json;
public JSONArray serialiseRequisionRO(CreateRequisitionRO[] requisitionRO) {
JSONSerializer serializer = new JSONSerializer();
List<String> requisitionROList = new ArrayList<String>();
for(int i = 0 ; i< requisitionRO.length ; i++)
{
requisitionROList.add(serializer.serialize(requisitionRO[i]));
}
System.out.println("JSON : "+serializer.serialize(requisitionRO[0]));
return convertListToJSON(requisitionROList);
}
#SuppressWarnings("unchecked")
public JSONArray convertListToJSON(List<String> requisitionROList){
JSONArray requestCollection = new JSONArray();
JsonFactory jsonFactory = new JsonFactory();
for(int i = 0 ; i< requisitionROList.size() ; i++)
{
requestCollection.add(requisitionROList.get(i));
}
return requestCollection;
}
after doing all these i get the following exception -- java.io.EOFException: No content to map to Object due to end of input
I am in the guessing of that I do not set the parameter correctly I suppose but I am not sure about this.
Please help me to resolve this as I am struggling with this for more than three days.
I got the above java.io.EOFException: No content to map to Object due to end of input it is because the calling expects some argument where as i have sent the request without arguments.and this can also occur i the argument takes json array as parameter but i was sending json string which also was casting me the same exception.