GWT RequestBuilder - Cross Site Requests - java

I'm trying to make Cross Site Request using GWT Request builder, which i couldn't get it to work yet. As you can see, this is much of a Sample GWT Project and i have gone through https://developers.google.com/web-toolkit/doc/latest/tutorial/Xsite . But still i'm missing something.
I'm Posting the code here. What am i missing ..?
package com.gwt.reqbuilder.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Window;
public class GWTRequestBuilder implements EntryPoint
{
private static final String JSON_URL = "http://localhost:8000/?q=ABC&callback=callback125";
public void onModuleLoad()
{
GWTPOSTHTTP();
}
public void GWTPOSTHTTP()
{
String postUrl="http://localhost:8000";
String requestData="q=ABC&callback=callback125";
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, postUrl);
try {
builder.sendRequest(requestData.toString(), new RequestCallback()
{
public void onError(Request request, Throwable e)
{
Window.alert(e.getMessage());
}
public void onResponseReceived(Request request, Response response)
{
if (200 == response.getStatusCode())
{
Window.alert(response.getText());
} else {
Window.alert("Received HTTP status code other than 200 : "+ response.getStatusText());
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
Window.alert(e.getMessage());
}
}
}

Actually we can make Cross Site Requests from GWT RequestBuilder if we can set in Servlet Response Header
Response.setHeader("Access-Control-Allow-Origin","http://myhttpserver");
It's working Cool , if anyone need the GWT Project and Python Servlet, please do let me know, i can upload the files.
GWT Client Code : https://github.com/manikandaraj/MLabs/tree/master/GWT/GWTClient

You've missed to finish reading the tutorial.
Direct quote from the tutorial :
The RequestBuilder code is replaced by a call to the getJson method. So you no longer need the following code in the refreshWatchList method:
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
try {
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
displayError("Couldn't retrieve JSON");
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
updateTable(asArrayOfStockData(response.getText()));
} else {
displayError("Couldn't retrieve JSON (" + response.getStatusText()
+ ")");
}
}
});
} catch (RequestException e) {
displayError("Couldn't retrieve JSON");
}
Which is broadly what you've got, and should be replaced by a JSNI function given in the tutorial a few lines below :
/**
* Make call to remote server.
*/
public native static void getJson(int requestId, String url,
StockWatcher handler) /*-{
var callback = "callback" + requestId;
// [1] Create a script element.
var script = document.createElement("script");
script.setAttribute("src", url+callback);
script.setAttribute("type", "text/javascript");
// [2] Define the callback function on the window object.
window[callback] = function(jsonObj) {
// [3]
handler.#com.google.gwt.sample.stockwatcher.client.StockWatcher::handleJsonResponse(Lcom/google/gwt/core/client/JavaScriptObject;)(jsonObj);
window[callback + "done"] = true;
}
...

Related

OkHttpClient authenticator without retrofit

Im trying to refresh an Access token in my application following this solution.
My actual problem is handling the callback and then return the new request in the authenticate method.
I tried using an interface to return a String from my callback method but then I cant assign it to a variable, nor can I return the new request from there since its inside my onResponseListener.
How can I solve this issue?
public Request authenticate(Route route, Response response) throws IOException {
// GetAuthRequest is a void method, and I cant assign a String value on the callback.
getAuthRequest(new AuthResponse() {
#Override
public Request onSuccess(String token) {
return response.request().newBuilder()
.header("Authorization", "Bearer " + token)
.build();
}
});
I was using an Asynchronous call instead of Synchronous. Ended up making a method that returns an String like so:
private String getAuthRequest() {
// Make the request above
try (Response response = httpClient.newCall(request).execute()) {
JSONObject jsonObject = new JSONObject(response.body().string());
return jsonObject.getString("access_token");
} catch (IOException | JSONException e) {
e.printStackTrace();
}
return null;
}

GWT - How to return a String value from RequestBuilder after receiving a response?

I'm unable to figure out how to return a String value from RequestBuilder's sendRequest() method after receiving a response. I referred to a similar question where the suggestion was to use Callback<String, String> callback but I can't figure out how to implement this. The GWT documentation for Callback does not have any examples.
What I have is a class Requester with the method generateRequest() that should make a request with RequestBuilder and return a String when called. The processResponse() method takes the response, parses it and returns a String which I'm storing in output. How can I return this output String when generateRequest() is called from another class?
public String generateRequest() {
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url.getUrl()));
builder.setHeader("Authorization", authHeader);
String title = null;
try {
builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
GWT.log(exception.getMessage());
}
public void onResponseReceived(Request request, Response response) {
String output = processResponse(response);
}
});
} catch (RequestException e) {
GWT.log(e.getMessage());
}
return title;
}
I think you might be misunderstanding something.
You cannot simply return a String because the call is async (i.e. you can't return the String because the String is simply not available yet, at the time you wish to return it).
You could simply wait there until the call result is ready, but this is really terrible practice; that's why you're seeing people suggesting callbacks.
Imagine, this is the code:
statement01;
statement02;
String result = generateRequest(...);
statement04UsingResult;
statement05;
then this will not work, because result will not be available before statement04UsingResult is executed. The Request has not finished yet. (as Andrej already mentioned)
To solve this, split your code:
statement01;
statement02;
generateRequest(...);
create an new void method, wich accepts the result as parameter:
public void newMethod(String result) {
statement04UsingResult;
statement05;
}
and call from inside the onResponseRevieve-method:
builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
GWT.log(exception.getMessage());
}
public void onResponseReceived(Request request, Response response) {
newMethod(processResponse(response));
}
});
Hope that helps.

calling some online service from GWT

I have this JavaScript code which is connecting with the service and sending back the result.
Now the requirement is to call the same service from Pure Java.
Below is the javascript code for calling the service.
If some one can guide me to convert this Javascript to Java in my GWT Application
Thanks
function verifyValidationSyntax(textToValidate)
{
var url = "https://validation-grammar.example.com/validation_grammar_service/rest/validation_step_validation";
var client = new XMLHttpRequest();
client.open("POST", url, false);
client.setRequestHeader("Content-Type", "text/plain");
client.send(textToValidate);
if (client.responseText==='true') {
return "true";
} else {
return "false";
}
}
I wont convert your code, But here is the sweetest example from docs
String url = "http://www.myserver.com/getData?type=3";
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url));
try {
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// Couldn't connect to server (could be timeout, SOP violation, etc.)
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
// Process the response in response.getText()
} else {
// Handle the error. Can get the status text from response.getStatusText()
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
}
You may miss this in docs
To use the HTTP types in your application, you'll need to first inherit the GWT HTTP module by adding the following tag to your module XML file:
<inherits name="com.google.gwt.http.HTTP" />

GWT Request Builder is not working in production but working in development

I'm using GWT and creating a HTTP request but I'm having issues accessing the file from the production version, even though it's working fine in development. My main program has the following for the request on the client side.
static final String dataURL = GWT.getModuleBaseURL() + "interpretData";
public void onModuleLoad() {
requestData(dataURL, new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
RootPanel.get(holderId).add(new Label(error + ": Asynchronous call failed - " + caught.getLocalizedMessage()));
return;
}
public void onSuccess(String JSON){
try{
// code executed on success
} catch (Exception e) {
RootPanel.get(holderId).add(new Label(error + ": " + e.getMessage()));
return;
}
}
});
}
public static void requestData(final String url, final AsyncCallback<String> callback) {
// create a request for the xml data on the server
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
builder.setCallback(new RequestCallback() {
public void onError(Request request, Throwable exception) {
callback.onFailure(exception);
}
public void onResponseReceived(Request request, Response response) {
try {
final int responseCode = response.getStatusCode() / 100;
if (url.startsWith("file:/") || (responseCode == 2) || (responseCode == 0)){
callback.onSuccess(response.getText());
} else {
callback.onFailure(new IllegalStateException(" Http Error: #" + response.getStatusCode() + " - " + response.getStatusText()));
}
} catch (Throwable e) {
callback.onFailure(e);
}
}
});
On the server side, I have:
public class interpretData extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
response.setContentType("application/json");
// code to return a String
}
Finally, my XML file has the following in it:
<servlet>
<servlet-name>interpretData</servlet-name>
<servlet-class>com.gmod.caeli.server.interpretData</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>interpretData</servlet-name>
<url-pattern>/caeli/interpretData</url-pattern>
</servlet-mapping>
In the end, I can access the file from: http://127.0.0.1:8888/caeli/interpretData so the development version is completely fine, but I don't know how to get it to work in production (the URL I'm calling for production is file:///~/workspace/Caeli/war/caeli/interpretData) I've searched for examples, but I haven't found any clues to what I'm doing wrong. I tried using setting it up with tomcat and I got a 404 error there too. I feel like I'm missing something small, so hopefully this is enough information for someone to notice something wrong.
From my experience and research, the URL that your attempting to request in production (file:///...) cannot be requested by the web browser via an Ajax call, anchor tag, javascript etc. It might be a little confusing/misleading as you can enter that URL into your browser manually and get the expected result, however this local resource request is not allowed by the browser.

How enable JSONP in RESTEasy?

Title say about my issue. I need wrap DTO in to a javascript method callback. Currently I return on request JSON. But problem with using this in Ajax because I send GET to other domain. and of course security police.
I have idea to create addition provide. Have you any example, links or suggestion how can do this.
There's no explicit support for JSONP in RESTEasy, however one easy way to enable JSONP in your application is to write a Servlet Filter.
Here's a few links that can help you write a filter:
jsonp-java: server side filter wraps any response into a jsonp callback
Serving up JSONP from your JAX-RS Web Services
Implementing a Servlet Filter for JSONP callback with Spring’s DelegatingFilterProxy (if you're using Spring)
When I had this requirement I ended up writing my own since none of the examples I found seemed to quite nail it. Here's my advice for writing your own filter:
only wrap the response if a callback parameter is specified (obviously)
only wrap the response if the response content type is application/json (or if you want to support a wider selection of variants, only wrap if the response content type is application/json or application/*+json)
use an HttpServletResponseWrapper so that you can invoke the forward chain (chain.doFilter) without writing any data to the real response. Once the forward chain is complete you can then check the content type, make sure you want to wrap the response as JSONP, then write the captured data into the real response, along with the JSONP prefix and suffix.
when you do decide to wrap the response as JSONP, make sure you change the response content type to text/javascript
If you haven't done much with Java EE Filters before, you may want to read the relevant section of the Java EE tutorial first: Filtering Requests and Responses.
I make draft workaround for this problem. Try it. This solution takes data via http get parameters and translate to virtual POST request.
JQuery:
function call(){
var val = '{"routes":[{"arrivalAddress":{"fullAddress":"DME"},"destinationAddress":{"fullAddress":"SVO"}}],"carsCount":"1"}';
var jHandler = "doMap";
$.getJSON("http://xxx:yyy/app-0.0.0.1/rest/requestPrice?callback=" + jHandler + "&json=" + encodeURIComponent(val)+"&jsoncallback=?", null, null, "json");
}
function doMap(obj){
alert(obj);
}
Declaration in Service interface
#POST
#Path("requestPrice")
#Produces("application/json")
#Consumes("application/json")
PriceResponse requestPrice(PriceRequest request) throws ServiceException;
Filter class:
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class JSONPRequestFilter implements Filter {
private String callbackParameter;
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (!(request instanceof HttpServletRequest)) {
throw new ServletException("This filter can " +
" only process HttpServletRequest requests");
}
final HttpServletRequest httpRequest = (HttpServletRequest) request;
final HttpServletResponse httpResponse = (HttpServletResponse) response;
if (isJSONPRequest(httpRequest)) {
RequestWrapper requestWrapper = new RequestWrapper(httpRequest);
requestWrapper.setContentType("application/json; charset=UTF-8");
requestWrapper.setHeader("cache-control", "no-cache");
requestWrapper.setHeader("accept", "application/json");
requestWrapper.setCharacterEncoding("UTF-8");
requestWrapper.setBody(httpRequest.getParameter("json"));
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(httpResponse) {
#Override
public ServletOutputStream getOutputStream() throws IOException {
return new ServletOutputStream() {
#Override
public void write(int b) throws IOException {
baos.write(b);
}
};
}
#Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(baos);
}
public String getData() {
return baos.toString();
}
};
chain.doFilter(requestWrapper, responseWrapper);
response.getOutputStream().write((getCallbackParameter(httpRequest) + "(").getBytes());
response.getOutputStream().write(baos.toByteArray());
response.getOutputStream().write(");".getBytes());
response.setContentType("text/javascript");
} else {
chain.doFilter(request, response);
}
}
private String getCallbackMethod(HttpServletRequest httpRequest) {
return httpRequest.getParameter(callbackParameter);
}
private boolean isJSONPRequest(HttpServletRequest httpRequest) {
String callbackMethod = getCallbackMethod(httpRequest);
return (callbackMethod != null && callbackMethod.length() > 0);
}
private String getCallbackParameter(HttpServletRequest request) {
return request.getParameter(callbackParameter);
}
public void init(FilterConfig filterConfig) throws ServletException {
callbackParameter = filterConfig.getInitParameter("callbackParameter");
}
public void destroy() {
}
void printRequest(HttpServletRequest request) throws IOException {
{
System.out.println("--------------Headers---------------");
Enumeration en = request.getHeaderNames();
while (en.hasMoreElements()) {
String val = en.nextElement().toString();
System.out.println(val + " :");
Enumeration en1 = request.getHeaders(val);
while (en1.hasMoreElements()) {
System.out.println("\t" + en1.nextElement());
}
}
}
{
System.out.println("------------Parameters--------------");
Enumeration en = request.getParameterNames();
while (en.hasMoreElements()) {
String val = en.nextElement().toString();
System.out.println(val + " :");
String[] en1 = request.getParameterValues(val);
for (String val1 : en1) {
System.out.println("\t" + val1);
}
}
}
System.out.println("---------------BODY--------------");
BufferedReader is = request.getReader();
String line;
while ((line = is.readLine()) != null) {
System.out.println(line);
}
System.out.println("---------------------------------");
System.out.println("ContentType: " + request.getContentType());
System.out.println("ContentLength: " + request.getContentLength());
System.out.println("characterEncodings: " + request.getCharacterEncoding());
System.out.println("AuthType: " + request.getAuthType());
System.out.println("ContextPath: " + request.getContextPath());
System.out.println("Method: " + request.getMethod());
}
public static class RequestWrapper extends HttpServletRequestWrapper {
Map<String, String> headers = new HashMap<String, String>();
int contentLength;
BufferedReader reader;
public RequestWrapper(HttpServletRequest request) {
super(request);
}
public void setHeader(String key, String value) {
headers.put(key, value);
}
ByteArrayInputStream bais;
public void setBody(String body) {
bais = new ByteArrayInputStream(body.getBytes());
contentLength = body.length();
headers.put("content-length", Integer.toString(contentLength));
}
#Override
public BufferedReader getReader() throws IOException {
reader = new BufferedReader(new InputStreamReader(bais));
return reader;
}
#Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStream() {
#Override
public int read() throws IOException {
return bais.read();
}
};
}
#Override
public String getMethod() {
return "POST";
}
private String contentType;
public void setContentType(String contentType) {
this.contentType = contentType;
headers.put("content-type", contentType);
}
#Override
public String getContentType() {
return contentType;
}
#Override
public int getContentLength() {
return contentLength;
}
#Override
public String getHeader(String name) {
String val = headers.get(name);
if (val != null) {
return val;
}
return super.getHeader(name); //To change body of overridden methods use File | Settings | File Templates.
}
#Override
public Enumeration getHeaders(final String name) {
return super.getHeaders(name);
}
#Override
public Enumeration getHeaderNames() {
final Enumeration en1 = super.getHeaderNames();
final Iterator it = headers.keySet().iterator();
return new Enumeration() {
public boolean hasMoreElements() {
return en1.hasMoreElements() || it.hasNext();
}
public Object nextElement() {
return en1.hasMoreElements() ? en1.nextElement() : (it.hasNext() ? it.next() : null);
}
};
}
#Override
public int getIntHeader(String name) {
String val = headers.get(name);
if (val == null) {
return super.getIntHeader(name);
} else {
return Integer.parseInt(val);
}
}
}
}
web.xml
<filter>
<filter-name>JSONPRequestFilter</filter-name>
<filter-class>xxxxx.JSONPRequestFilter</filter-class>
<init-param>
<param-name>callbackParameter</param-name>
<param-value>callback</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>JSONPRequestFilter</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>
An enhancement to support JSONP is scheduled to be released in RESTEasy 2.3.6 Final/3.0-beta-4 (https://issues.jboss.org/browse/RESTEASY-342). I was able to "backport" it my project which uses RESTEasy 2.3.5 by simply copying their code from GitHub.
RESTEasy automatically picks up the new provider based on the annotation. It works automatically by wrapping your results in a js callback once it sees a query parameter named "callback" in the url. This is compatible with what JQuery sends to the server for JSONP requests.
To follow on from #talawahdotnet, I'm using RestEasy 3.0.9.Final and there is support for JSONP, once enabled, any request with a "callback" query parameter will be wrapped as JSONP. I'm using JBoss so the full docs are here for other containers. Here's the steps I had to do:
In your web.xml add:
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>org.jboss.resteasy.plugins.providers.jackson.JacksonJsonpInterceptor</param-value>
</context-param>
Make sure you have a WEB-INF/jboss-deployment-structure.xml with:
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.jboss.resteasy.resteasy-jackson-provider" services="import" annotations="true"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
Make sure you have a resteasy-jackson-provider dependency in your pom.xml, something like:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<scope>provided</scope>
</dependency>
Resteasy claims to support JSONP out of the box in 3.x version:
If you're using Jackson, Resteasy has JSONP that you can turn on by
adding the provider
org.jboss.resteasy.plugins.providers.jackson.JacksonJsonpInterceptor
(Jackson2JsonpInterceptor if you're using the Jackson2 provider) to
your deployments. If the media type of the response is json and a
callback query parameter is given, the response will be a javascript
snippet with a method call of the method defined by the callback
parameter. For example:
GET /resources/stuff?callback=processStuffResponse will produce this
response:
processStuffResponse() This supports the default
behavior of jQuery.
You can change the name of the callback parameter by setting the
callbackQueryParameter property.
However, it seems that it is broken due to RESTEASY-1168: Jackson2JsonpInterceptor does not render closing bracket
So
foo({"foo":"bar"}
is rendered instead of
foo({"foo":"bar"})
And that causes "Uncaught SyntaxError: Unexpected Identifier" error
I have submitted a pull-request with a fix and hopefully it should get into next release 3.0.12
I know that this question is pretty old, but it is shown on the first page of Google when you search for resteasy jsonp problems, so I decided to update it

Categories

Resources