best practice invoking webservices - java

I'm doing a school project where we are supposed to tap into an existing database using web services. I'm trying to figure out what best practice is when calling a web service from back end. I've been working with Servlets before and I know them pretty well.
This is my web service that front end uses and I need to know what the best practice is when calling an external web service within my application:
#GET
#Path("requestAccess")
public void getAccessToken(#Context HttpServletRequest request, #Context HttpServletResponse response)
{
String code = request.getParameter("code");
String clientId = "4_4inr3rkl04ys44kowwgoo0w4g8gow0s84cw0o0cg48kogsosc0";
String clientSecret = "4cxgpduio8isgcc8oggsw8wkcokcksk8wc8cc088w4w40owg4s";
String redirectUrl = "http://localhost:8080/salesgoals/rest/oauth/requestAccess";
try {
URL url = new URL("https://.../oauth/v2/token?client_id="+clientId+"&client_secret="+clientSecret+"&grant_type=authorization_code&redirect_uri="+redirectUrl+"&code="+code);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
String strTemp = "";
while(null != (strTemp = bufferedReader.readLine())){
System.out.println(strTemp);
}
} catch(Exception e){e.printStackTrace();}
}
This returns me an access token and the results from the external web service are JSON objects and the url object with inputstreamReader is something temp. I used to see if I was successful receiving access token.
Now I need to use the access token to invoke external web services but I dont know what best practice is when it comes to calling it within the application. I'm used to HttpServletRequest/Response objects. As I said all the data is returned as json.

I doubt there is 100% best practice, but take a look at
Jersey
It is both client and server RESTful web services implementation.

Related

How to process a request to an external REST service and return the response to Google Assistant?

I am using Java to create an app for Google Assistant that will call an external REST API and return certain responses based on trigger phrases.
I currently can use the Default Welcome Intent to return simple text responses through the Actions on Google simulator. However, when I try to call an external REST API and send back a response, the simulator returns a message that says:
"MalformedResponse: Failed to parse Dialogflow response into AppResponse because of empty speech response."
I am using the org.springframework.web.client.RestTemplate from Spring-framework to process the result from the REST Service (https://fitzroi-rest-api-0525.appspot.com/rest/Fitz) with the following call:
greeting = restTemplate.getForObject("https://fitzroi-rest-api-0525.appspot.com/rest/{name}", Greeting.class, givenName); (This works well in a regular Spring project, but not within the Actions on Google Intent)
An example training phrase for my test app is "Tony is sending greetings." From here I am extracting "Tony" as a #sys.given-name entity in Dialogflow. This name is then passed to the REST serivice for processing. The REST service is an MVC app that is running in a separate Google Cloud project from the Google Assistant App.
Please let me know if this is a good approach to consume a REST service using Dialogflow fullfillment webhook.
Below is a sample code from my webhook that is trying to consume the REST service.
#ForIntent("process-greeting")
public ActionResponse greetingProcessor(ActionRequest request) {
LOGGER.info("Trying to process greeting intent");
ResponseBuilder responseBuilder = getResponseBuilder(request);
String givenName = (String) request.getParameter("given-name");
if (givenName != null && !givenName.isEmpty()) {
RestTemplate restTemplate = new RestTemplate();
Greeting greeting = null;
greeting = restTemplate.getForObject("https://fitzroi-rest-api-0525.appspot.com/rest/{name}", Greeting.class, givenName);
// LOGGER.info("Attempting to send back " + greeting.getContent() + " to Google Assistant");
if (greeting == null)
responseBuilder.add("The rest service did not return a response.");
else
responseBuilder.add(greeting.getContent());
}
LOGGER.info("Welcome intent end.");
return responseBuilder.build();
}
It seems that since actions-on-google requires thread-safe function calls, the RestTemplate from spring-framework does not work in an app-engine app. I was able to find a walk-around by using a sample code provided by the actions-on-google team on GitHub. This code requires that you parse the results from the URL from within the ActionsApp instead of using a library. For example:
URL restURL = new URL("http://yourdomain.com/your/rest/call");
URLConnection conn = restURL.openConnection();
InputStreamReader reader = new InputStreamReader(
(InputStream) conn.getContent());
JsonParser parser = new JsonParser();
JsonElement root = parser.parse(reader);
MyObject = myParseFunction(root);
I also had a serious issue (UnKonwnHostException) parsing the results from a remote URL. This documentation was helpful.

Code position of keystore and truststore in java servlet

I'm working with an organization's payment API. The API automatically posts a soap request to our server when a customer makes payment and I response with an acknowledgement message in xml. (Check out the screenshots show a simple demonstration in SOAP UI)
SOAP UI Test Response
SOAP UI Test Raw XML
I made this code in Java to receive the soap request and send a response.
`public class testsoap extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/xml;charset=UTF-8");
ServletInputStream out = request.getInputStream();
String xmlrpc = "";
int c = 0;
while((c = out.read()) != -1 ){ xmlrpc += (char)c; }
int startTag = xmlrpc.indexOf("<TransID>");
int endTag = xmlrpc.indexOf("</TransID>");
String parameter = xmlrpc.substring(startTag,endTag).replaceAll("<TransID>","");
String result="";
//result +="<?xml version=\"1.0\"?>\n";
result +="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:c2b=\"http://cps.huawei.com/cpsinterface/c2bpayment\">\n";
result +="<soapenv:Header/>\n";
result +="<soapenv:Body>\n";
result +="<c2b:C2BPaymentConfirmationResult>C2B Payment Transaction "+parameter+" result received.</c2b:C2BPaymentConfirmationResult>\n";
result +="</soapenv:Body>\n";
result +="</soapenv:Envelope>\n";
response.getWriter().println(result);
}
}`
Now I need to add the location of my keystore and truststore.
Should I add this code just before I start preparing a response?
` System.setProperty("javax.net.ssl.keyStore",path_to_keystore);
System.setProperty("javax.net.ssl.keyStorePassword",akeystorepassword);
System.setProperty("javax.net.ssl.trustStore",path_to_your_cacerts_file);
System.setProperty("javax.net.ssl.trustStorePassword",atrustsorepassword)`
Or do I need to make a snippet that makes secure connection using the keystore and truststore rather than just setting a system property?
Create a Java class and write all the functionalities that you need to publish as a methods. Then you need to publish those functionalities as a WSDL to be consumed by your clients. See the following tutorial that will take you in step by step to publish a web services:
Step by Step JAX-WS Web Services with Eclipse, TomEE, and Apache CXF
Building a Simple Web Service ? A Tutorial
Implementing a simple web service
Further based on your requirements you can have complex object as an input parameter like C2BPaumentConfirmationRequest and KYCInfo in your case

How to propagate an HttpServletResponse to a client?

We're working on a new web application to replace an old one that is commonly being used by our company. They both will ultimately have the exact same API. What we'd like to do initially is test out the new functionality by having clients send requests to the new web app, but then have our new web app propagate their requests to the old web app and send the old web app's http responses back to our clients (so that from client point of view, nothing has changed).
What I'd like to do is get the exact HttpServletResponse object that we're getting back from the old web app and send that back to clients of the new web app. What is the best way of performing this? I know that once I can retrieve the HttpServletResponse, I can just set it equal to the one we have as a parameter to our functions (API handlers) in our new web app's REST controller, but I'm having trouble retrieving it.
Is there any way of retrieving the HttpServlet response via Spring's RestTemplate?
You can use org.apache.commons.httpclient.HttpClient
It has public int executeMethod(HttpMethod method) where you can define request and after checking status is success
you can use all the HttpMethod methods.
InputStream getResponseBodyAsStream()
Header[] getResponseHeaders();
and pass to your response. Like this
public static void main(String[] args) throws Exception {
HttpClient client = new HttpClient();
GetMethod method = new GetMethod("http://The old service url");
method.addRequestHeader("X-Username", "user");
method.addRequestHeader("X-Password", "password");
// Execute the HTTP GET request
int status = client.executeMethod(method);
if(status == 200){
InputStream in = method.getResponseBodyAsStream();
OutputStream out=the out of your response
IOUtils.copy(in, out);
in.close();
out.flush();
out.close();
}
}

How to download file from web site having liferay portlet using java code

i'm trying to download a file from a site , this site has a life ray server
i have been reading to much about but all describe how to configure a server not how to read from , all examples i saw has HTTPServletRequest which needs a request input how can i transfer a URL to a request ,from where to start at least .
in other words :i have the URL , in the webpage i select a date and a download like is generated , how can i make it down in java ????
i tried this:
HttpServletRequest request = PortalUtil.getHttpServletRequest(PortletRequest);
so how to link my URL to PortletRequest
If you have the URL of the download the only thing you need is to perform a client request against that URL.
First thing you should try to be sure that the URL you have is the one that will give you the expected results is try to paste it in a new browser window and verify that the download starts.
Then, if you want to perform that download through Java you can do very easily using the URL and URLConnection (HttpURLConnection in this case) classes:
String urlString = "..."; // Your URL
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() == 200) {
InputStream stream = conn.getInputStream();
// Read the data from the stream
}
You could also do the same using Apache HTTP Client.
Note: PortalUtil.getHttpServletRequest(...) is used internally by Liferay and you won't have any access to that API if you are doing a client request.
If you're writing a portlet, by design you don't get access to the HttpServletRequest.
What you can do is to utilize the "resource-serving" lifecycle phase of a portlet. There you get access to a ResourceRequest and ResourceResponse object. Those objects behave almost like a HttpServletRequest/-Response object
As you don't name the framework that you're using: javax.portlet.GenericPortlet.serveResource() is the method that you want to override in the pure JSR-286 API.
On the UI side, <portlet:resourceURL/> will provide the URL to your portlet's resource handling method.
This should provide you with enough google-food to find tutorials on how to implement different lifecycle phases - I can't judge the required level of detail you need. Note that Liferay has quite a few sample portlets that you can utilize as a source for sample code.
Edit: Following your comment below, let me give you some pseudo code (just typed here, never compiled/run):
on a jsp frontend, e.g. view.jsp:
Download File
Then, in your portlet, assuming you're implementing javax.portlet.GenericPortlet in one way or another (e.g. indirectly through Liferay's MVCPortlet or any other superclass):
public class MyPortlet extends GenericPortlet {
....
#Override
public void serveResource(ResourceRequest request, ResourceResponse response) {
// implement the file streaming here,
// use ResourceResponse the way you find illustrated
// in samples for HttpServletResponse
}

how to write a file object on server response and without saving file on server?

I am using Spring with DWR . I want to return a file object as response , however I save the file (to be sent) at server temporary location and then send its location as href for anchor tag on client side , however I wonder if there could be a way to throw the file directly to browser on response object without saving it temporarily on server.
I expected if there could be a way to send file as a response via DWR.
public ModelAndView writeFileContentInResponse(HttpServletRequest request, HttpServletResponse response) throws IOException {
FileInputStream inputStream = new FileInputStream("FileInputStreamDemo.java"); //read the file
response.setHeader("Content-Disposition","attachment; filename=test.txt");
try {
int c;
while ((c = inputStream.read()) != -1) {
response.getWriter().write(c);
}
} finally {
if (inputStream != null)
inputStream.close();
response.getWriter().close();
}
}
It has been years since I've used Spring, and I'm unfamiliar with DWR, but the essence of your question is basic to the web.
The answer is yes, you can. In effect, you need to set the HTTP header Content-Disposition: attachment, then stream down the contents. All of this will be in the response to the original request (as opposed to sending back a link).
The actual code to achieve this will depend on your circumstances, but this should get you started.
you call the method from Java Script, right? I didn't really understand how Spring is related in this flow, but as far as I know DWR allows you to produce Java Script Stubs and call the Java methods of the exposed bean directly on server right from your java script client code.
You can read the file byte-by-byte and return it from your java method as long as it really returns a byte array.
However what would you do with this byte array on client?
I just think in this specific flow you shouldn't use the DWR but rather issue an ordinar AJAX request (if DWR can wrap it somehow for convenience - great). This request shouldn't come to DWRServlet, but rather be proceeded by a regular servlet/some web-based framework, like Spring MVC :)
Once the request comes to the servlet, use
response.setHeader("Content-Disposition","attachment; filename=test.txt");
as was already stated.
Hope this helps,
Good luck!
Mark
An example which return a excel to download from client:
//Java side:
public FileTransfer getExcel(Parametros param){
byte[] result = <here get data>;
InputStream myInputStream = new ByteArrayInputStream(result);
String excelFormat = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
FileTransfer dwrExcelFile = new FileTransfer("excel.xlsx", excelFormat, myInputStream);
return dwrExcelFile;
}
//Javascript side:
function downloadExcelFile() {
dwr.engine.setTimeout(59000);
var params = <params_to_send>;
<Java_class>.getExcel(params, {callback:function(dataFromServer) {
downloadExcelCallback(dataFromServer);
}});
}
function downloadExcelCallback(data) {
dwr.engine.openInDownload(data);
}

Categories

Resources