Reflection - can't call java method from JSON-RPC request - java

I want to call a method based on JSON-RPC request from a servlet I have code like this:
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
ServletInputStream in = request.getInputStream();
PrintWriter out = response.getWriter();
String json_request = this.readStream(in);
Object id = null;
try {
JSONRPC2Request reqIn = JSONRPC2Request.parse(json_request);
id = reqIn.getID();
Object params = reqIn.getPositionalParams().toArray();
String method_name = reqIn.getMethod();
Service service = new Service();
Method[] methods = service.getClass().getMethods();
Method method = null;
// getMethod need class as second argument
for (int i=0; i<methods.length; ++i) {
if (methods[i].getName().equals(method_name)) {
method = methods[i];
break;
}
}
if (method != null) {
Object result = method.invoke(service, params);
JSONRPC2Response respOut = new JSONRPC2Response(result, id);
out.println(respOut);
} else {
out.println(JSONRPC2Error.METHOD_NOT_FOUND);
}
} catch (IllegalArgumentException e) {
out.println(new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, id));
} catch (IllegalAccessException e) {
out.println(new JSONRPC2Response(JSONRPC2Error.INTERNAL_ERROR, id));
} catch (InvocationTargetException e) {
out.println(new JSONRPC2Response(JSONRPC2Error.INTERNAL_ERROR, id));
} catch (JSONRPC2ParseException e) {
out.println("{\"error\": \"Parse Error: " + e.getMessage() + "\"}");
}
}
I try to call method login from service class:
public class Service {
public String login(String username, String password) {
return "token";
}
}
I call it from javascript using jQuery:
var request = JSON.stringify({
method: "login",
params: ["foo", "Bar"],
id: 1,
jsonrpc: "2.0"
});
$.post('/app/rpc', request, function(res) { console.log(res); });
But I keep getting runtime IllegalArgumentException. What's wrong with my code? I also try to cast params to object with the same result.

Related

Version control for java restful servlet

We need to apply version control for our API, when the user send a request to our API endpoint i.e."http://mycompany/item?version=1", it will forwarded the request to itemServer_V1.java.
To achieve this goal, we have configured our web.xml as follows.
<servlet>
<servlet-name>item</servlet-name>
<servlet-class>com.mycompany.Servlet.ItemRequestHandler</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>item</servlet-name>
<url-pattern>/item</url-pattern>
</servlet-mapping>
We create a table in MySQL database.
database table
ItemRequestHandler is a class which extends HttpServlet, and it supposed to forward the request to ItemServiceV1 or ItemServiceV2 according to the version parameter in the request.
I have finish the ItemService class but I don't know how to forward the request from ItemRequestHandler to ItemService class. Could someone let me know how to do that please?
ItemRequestHandler class is as follows
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException , IOException
{
String version = req.getParameter("version");
String fcd = req.getParameter("fcd");
String client = req.getParameter("client");
//Find the targetClass from database using the above information.
targetClass.doGet(req, res);
}
I find out a solution.
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
System.out.println("LoginRequestHandler doPost");
String className = "";
String version = "";
String fcd = "login";
String compid = "";
RequestWrapper currentReq = new RequestWrapper(req);
version = currentReq.getParameter("Version");
compid = currentReq.getParameter("Compid ");
try {
className = findServletByVersion(compid, version, fcd);
Class<?> serviceClass = Class.forName(className);
Method method = serviceClass.getDeclaredMethod(MethodName.doPost.toString(), HttpServletRequest.class, HttpServletResponse.class);
method.invoke(serviceClass.newInstance(), currentReq, res);
return;
}catch(Exception e) {
System.out.println(e.toString());
} catch (DataNotFound e) {
System.out.println(e.toString());
}
}
}
Code of RequestWrapper
public class RequestWrapper extends HttpServletRequestWrapper {
private String _body;
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
_body = "";
BufferedReader bufferedReader = request.getReader();
String line;
while ((line = bufferedReader.readLine()) != null){
_body += line;
}
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(_body.getBytes());
return new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
#Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
Code of findServletByVersion
public String findServletByVersion(String compid, String version, String fcd) throws SQLException, ClassNotFoundException, DataNotFound {
String clsName = "";
Connection con = null;
Statement stmt = null;
User user = null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://YourIpAddress:PortNum/"+schemaName,"account","password");
String query = "SELECT * FROM "+compid+".restfcd "
+ "WHERE 1=1 "
+ "AND compid = '"+compid+"'"
+ "AND version = '"+version+"'"
+ "AND fcd = '"+fcd+"'"
+ "ORDER BY compid desc";
System.out.println(query);
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
if(rs!=null) {
while (rs.next()) {
clsName = rs.getString("fcdcls");
}
}
if(Func.isEmpty(clsName)) {
throw new DataNotFound("findServletByVersion : no match result!");
}
return clsName;
} catch (SQLException e) {
throw new SQLException("findServletByVersion : SQLException!");
} catch (ClassNotFoundException e) {
throw new ClassNotFoundException("findServletByVersion : ClassNotFoundException!");
} finally {
try {
con.close();
stmt.close();
} catch (SQLException sqlee) {
throw new SQLException("Cannot close conection/statement!");
}
}
}

Printing issue with internet download manager

I want to print a document in my java web application using servlet and i clear report info to avoid download resume(SecurityContext.cleanReportInfo()).
everything is ok when you don't have IDM in your system but when IDM is running it sends 2 request instead 1 and everything goes wrong by redirecting to /403 like the code below .
PrintReportServlet
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ReportDto reportInfo = SecurityContext.getReportInfo();
if (reportInfo != null) {
ServletOutputStream outputStream = response.getOutputStream();
try {
generateHeaders(response, reportInfo);
generateContents(outputStream, reportInfo);
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Error occurred during print report, nested error message: {0}", e.getMessage());
} finally {
outputStream.flush();
outputStream.close();
SecurityContext.cleanReportInfo();
}
} else {
response.sendRedirect(request.getContextPath() + "/403");
}
}
SecurityContext.java
public static void cleanReportInfo() {
SecurityContext.getCurrentSession().setAttribute("Report_Info", null);
}
errorreportController.js
$scope.printErrorList = function () {
errorReportService.printErrorList(function () {
window.open(contextPath + "/PrintReport");
});
};
ErrorReportController.java
#RequestMapping(value = "/printError", method = RequestMethod.GET)
#ResponseBody
public String printError() {
ReportDto reportDto = errorReportService.getReportInfo();
SecurityContext.setReportInfo(reportDto);
return success();
}
ErrorReportServiceImpl
public ReportDto getReportInfo() {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("jalaliDate", DateUtil.convertToJalali(new Date()).toStringBySlash());
parameters.put("alahImagePath", ReportUtil.getImagesPath() + File.separator + "alah.png");
parameters.put("sepahImagePath", ReportUtil.getImagesPath() + File.separator + "sepah.png");
parameters.put("reporter", SecurityContext.getCurrentUserName());
parameters.put("classify", "Normal");
parameters.put("userId",SecurityContext.getCurrentUserId());
ReportDto reportDto = new ReportDto(
ReportNames.ErrorReport, DataItems.Report_Type_PDF,
"error",
parameters);
return reportDto;
}

Multiple if else statement with parameter in doGet() servlet

I am having some problem when trying to execute different method in servlet doGet(). So when my button on click, it will pass along the eventID:
viewDtlEventBtn.setOnClickListener(new OnClickListener(){
public void onClick(View v){
Intent eventDtlIntent = new Intent(context, EventDetail.class);
eventDtlIntent.putExtra("eventID", eventIDTV.getText());
startActivity(eventDtlIntent);
}
});
Then in my EventDetail class, I am executing the method in AsyncTask class:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.event_detail);
context = this;
Bundle extras = getIntent().getExtras();
if (extras != null) {
eventID = extras.getString("eventID");
}
eventModel.setEventID(eventID);
new GetEventDetailAsyncTask(context).execute(eventModel);
}
And in my AsyncTask class, I am calling the method in my controller which retrieving the JSON returned from servlet:
#Override
protected Double doInBackground(Event... params) {
try {
eventCtrl.getEventDetailByID(params[0]);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
And in my controller class:
public Event getEventDetailByID(Event event) throws JSONException {
Event eventModel = new Event();
String page;
JSONArray jsonArray;
String eventID = event.getEventID();
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(ENeighbourhoodActivity.URL
+ "?getEventDetailByID&eventID=" + eventID +"");
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity, "UTF-8");
page = "{\'EventDetail\':" + responseString + "}";
try {
JSONObject jsonObject = new JSONObject(page);
jsonArray = jsonObject.getJSONArray("EventDetail");
int length = jsonArray.length();
for (int i = 0; i < length; i++) {
JSONObject attribute = jsonArray.getJSONObject(i);
String eventName = attribute.getString("eventName");
eventModel.setEventName(eventName);
}
} catch (JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return event;
}
And basically from here, I am accessing the servlet. And in my doGet() in serlvet class:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
JSONArray jsonArray = new JSONArray();
PrintWriter out = response.getWriter();
if (request.getParameter("getAllEvent") != null) {
}
catch (JSONException je) {
System.out.println(je.getMessage());
} catch (Exception exc) {
System.out.println(exc.getMessage());
}
out.println(jsonArray.toString());
}
}
I already have one if statement for some other methods. I wonder how should I pass the getEventDetailByID and the eventID parameter into servlet so that it knows which method to runs.
Thanks in advance.
Here is a example of how you can get the eventID value.
//gets value from getEventDetailByID parameter.
String detail = request.getParameter("getEventDetailByID");
if (detail != null && !detail.equals("")) {
int eventId = Integer.parseInt(request.getParameter("eventID"));
//get event detail by id with id
//e.g resultObject = myMethod(detail, eventId);
}
Update 1:
A better way of doing what is required:
String action = request.getParameter("action");
if (action.equalsIgnoreCase("GetById")) {
int eventId = Integer.parseInt(request.getParameter("eventID"));
//get event detail by id with id
//e.g resultObject = getById(eventId);
} else if (action.equalsIgnoreCase("GetAllEvents")) {
//Get all events
//e.g resultObject = GetAllEvents();
} else {
}
The URL usage:
to get event by id:
http://localhost:8080/WebService/EventDetailServlet?action=GetById&eventID=46
to get all event details
http://localhost:8080/WebService/EventDetailServlet?action=GetAllEvents

Not getting callbacks from my custom Cordova plugin (Android)

I created a plugin for multipart call and my plugin seems to work,
but when I call it this way:
multipart.uploadFiles(function() {
alert("success");
}, function() {
alert("errorr");
}, wsUrl, strArray, myRequest);
I dont get any callback, even if I print the proper response from my java code.
How to solve it?
Here is my js interface:
var multipart = {
uploadFiles: function (successCallback, errorCallback, serviceUrl, arrayRes, requestObject) {
cordova.exec(successCallback,
errorCallback,
"Multipart", // java class, service
"uploadFiles", // action
[{ // and this array of custom arguments to create our entry
"serviceUrl":serviceUrl,
"resPaths": arrayRes,
"requestObject": requestObject
}]
);
}
};
Here is my java code:
public class Multipart extends CordovaPlugin{
private static final String MULTIPART_TAG = null;
#Override
public boolean execute(final String action, final JSONArray args,
final CallbackContext callbackContext) throws JSONException {
final Context context = this.cordova.getActivity();
// sincronizza il modulo definito in action
cordova.getThreadPool().execute(new Runnable() {
#Override
public void run() {
try {
uploadFiles(context, action, args, callbackContext);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
return true;
}
private static void uploadFiles(Context context, String action, final JSONArray args, CallbackContext callbackContext) throws JSONException {
String requestURL = null;
JSONArray resPaths = null;
JSONObject requestObject = null;
String charset = "UTF-8";
JSONObject argObject = args.getJSONObject(0);
requestURL = argObject.getString("serviceUrl");
resPaths = argObject.getJSONArray("resPaths");
requestObject = argObject.getJSONObject("requestObject");
String request = requestObject.toString();
try {
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
multipart.addHeaderField("User-Agent", "CodeJava");
multipart.addHeaderField("Test-Header", "Header-Value");
multipart.addFormField("description", "descr");
multipart.addFormField("keywords", "Java,upload");
//multipart.addFormField("request", request);
multipart.addJsonField("request", request);
for (int i = 0; i < resPaths.length(); i++) {
File fileToPost = new File(resPaths.get(i).toString());
multipart.addFilePart("fileUpload", fileToPost);
}
List<String> response = multipart.finish();
System.out.println("SERVER REPLIED:");
for (String line : response) {
System.out.println(line);
}
} catch (IOException ex) {
System.err.println(ex);
}
}
}
I can't see any callbackContect.success or callbackContext.error calls in your Java code.

Sending an XML Object via HTTP POST

We are students.
In our project,we want to send xml block,basically saml assertion,from one server to another server via http post method.
Can anyone help us out in sending the XML object from one servlet to another servlet where each servlet resides on two different computers in java.
/* here we are trying to send xml object(root) from one servlet to another servlet which resides on different pc... but dispatcher method isnt working in this case.*/
public class sp1serv extends HttpServlet
{
public void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,java.io.IOException
{
Connection c=null;
Statement s= null;
ResultSet rs = null;
String d=null;
int flag=0;
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
Response response=null;
XMLObject root=null;
HttpSession session1=req.getSession();
System.out.println(session1.getAttribute("sAccessLevel"));
System.out.println(session1.getAttribute("sUserId"));
String eid=session1.getAttribute("sUserId").toString();
String[] str1 = {"response","attr",session1.getAttribute("sAccessLevel").toString(), session1.getAttribute("sUserId").toString() };
String filename= eid.concat(".xml");
try {
response=SAMLProtocol.passResponse(str1);
root=SAMLSignature.passSignature(response,filename);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
req.setAttribute("SP1",root);
String abc="http://169.254.229.232:8080/sp_response_handler";
RequestDispatcher rd=getServletContext().getRequestDispatcher(abc);
rd.forward(req, resp);
break;
}
}
}
}}
/* this servlet is used for retrieving xml object(root) and parsing it..on another server.*/
public class sp1_response_handler extends HttpServlet {
private static final long serialVersionUID = 1L;
public sp1_response_handler() {
super();
// TODO Auto-generated constructor stub
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
Response resp=null;
//XMLObject resp=null;
resp=(Response) request.getAttribute("SP1");
int result=0;
//SAMLSignature verification=null;
try {
result=SAMLSignature.verify(resp);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(result==1){
List attributeStatements = resp.getAssertions().get(0).getAttributeStatements();
for (int i = 0; i < attributeStatements.size(); i++)
{
List attributes = ((AttributeStatement) attributeStatements.get(i)).getAttributes();
for (int x = 0; x < attributes.size(); x++)
{
String strAttributeName = ((XMLObject) attributes.get(x)).getDOM().getAttribute("Name");
List<XMLObject> attributeValues = ((Attribute) attributes.get(x)).getAttributeValues();
for (int y = 0; y < attributeValues.size(); y++)
{
String strAttributeValue = attributeValues.get(y).getDOM().getTextContent();
System.out.println(strAttributeName + ": " + strAttributeValue);
}
}
}
response.sendRedirect("SP1.jsp");
}
else
{
System.out.println("NOT a Valid Signature");
}
}}
If you are using spring, you can use RestTemplate. From the docs:
String uri = "http://example.com/hotels/1/bookings";
PostMethod post = new PostMethod(uri);
// create booking request content
String request = post.setRequestEntity(new StringRequestEntity(request));
httpClient.executeMethod(post);
if (HttpStatus.SC_CREATED == post.getStatusCode()) {
Header location = post.getRequestHeader("Location");
if (location != null) {
System.out.println("Created new booking at :" + location.getValue());
}
}
Something like that should work (with the parameters being a Map<String,String>):
StringBuffer data = new StringBuffer();
if (parameters != null && parameters.size() > 0) {
for (Entry<String, String> e : parameters.entrySet()) {
if (data.length() > 0) {
data.append('&');
}
data.append(URLEncoder.encode(e.getKey(), "UTF-8")).append("=").append(URLEncoder.encode(e.getValue(), "UTF-8"));
}
}
String parametersAsString = data.toString();
// Send data
URL local_url = new URL(url);
URLConnection conn = local_url.openConnection();
conn.addRequestProperty("Content-Type", "text/xml; charset=utf-8");
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(parametersAsString);
wr.flush();
break;

Categories