gwt getModuleBaseURL on same server creates an java.lang.UnsatisfiedLinkError - gwt

I have a single GWT web-application integrated with Spring MVC. I have a working Controller which works perfectly and is unit tested to accept POSTed JSON data and returns JSON data.
From within the same application, to avoid any SOP cross-site domain issues, I am making a call with a RequestBuilder to POST the same json data, and I expect JSON data back.
I created a basic java class that should make a call, but I have a few issues. This running web-app is running in hosted mode in Jetty in Eclipse. I have done a ton of research on how GWT should make a call to an existing web-service with a simple HTP request.
The first issue from my unit test is that:
String baseUrl = GWT.getModuleBaseURL();
is not working and I get:
java.lang.UnsatisfiedLinkError: com.google.gwt.core.client.impl.Impl.getModuleBaseURL()Ljava/lang/String;
I think I know what the correct URL should be, so when I hard-code the url correctly, and execute this code:
String url = getRootUrl() + "rest/pendingInvoices/searchAndCount";
System.out.println("PendingInvoiceDataSource: getData: url=" + url);
// Send request to server and catch any errors.
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
builder.setHeader("Accept", "application/json");
builder.setHeader("Content-type", "application/json");
// builder.setRequestData(requestData);
try
{
System.out.println("PendingInvoiceDataSource: SEND REQUEST: getData: requestData=" + requestData);
Request request = builder.sendRequest(requestData, new RequestCallback()
{
public void onError(Request request, Throwable exception)
{
System.out.println("Couldn't retrieve JSON");
}
#Override
public void onResponseReceived(Request request, Response response)
{
if (200 == response.getStatusCode())
{
// updateTable(JsonUtils.safeEval(response.getText()));
System.out.println("data=" + response.getText());
}
else
{
System.out.println("Couldn't retrieve JSON (" + response.getStatusText() + ")");
}
}
});
}
catch (RequestException e)
{
System.out.println("Couldn't retrieve JSON");
}
I get this error on he sendRequest:
java.lang.UnsatisfiedLinkError: com.google.gwt.xhr.client.XMLHttpRequest.create()Lcom/google/gwt/xhr/client/XMLHttpRequest;
at com.google.gwt.xhr.client.XMLHttpRequest.create(Native Method)
at com.google.gwt.http.client.RequestBuilder.doSend(RequestBuilder.java:383)
at com.google.gwt.http.client.RequestBuilder.sendRequest(RequestBuilder.java:261)
I think this might be a quick fix, or maybe something small I have forgotten, so I'll try some more testing and see what I can find.

Everything client in GWT is only meant to run on the client-side: compiled to JS or in DevMode.
Only shared, server and vm classes can be used on the server-side.
If you want to get your server URL, use the appropriate methods from the HttpServletRequest (or whatever it is in Spring MVC as it seems from how you tagged the question that's what you're using).
If you want to make HTTP requests from your server, use an HttpURLConnection, or OkHttp, Apache Http Components or similar libraries, or even Spring's own HTTP client API.

Actually, it was only the Unit Test that was having a problem. Once I actually tried to run the deployed code, it all worked. I'll still try h GWTTestCase as suggested in order to get the unit test working.
But everything worked correctly when I ran the deployed code.
I also changed: String baseUrl = GWT.getModuleBaseURL();
which gave me:
http://localhost:8888/MyProject
To: String baseUrl = GWT.getHostPageBaseURL();
which gave me:
http://localhost:8888/
and that all worked.

Related

Spring Boot REST endpoint connection not being released

I have created Spring boot (2.1.4.RELEASE) REST endpoint to GET some data from the server. When I call this endpoint from the browser, I see the JSON in the browser window but I notice that the the spinner in fav icon is going on for 60 seconds. When i look at the network tab, I never see the response section for the request. After 60 seconds, it says that it failed. When I walk through the code in debugger, I see that data is being returned from the controller and when I 'play' the rest of the stack everything completes (thread that is being assigned to serve the request) I am kind of puzzled what's causing this behavior.
#GetMapping(path="/recipes")
public ResponseEntity<Collection<HpManifest>> getRecipes() {
ResponseEntity<Collection<HpManifest>> response = hpService.getRecipes();
return response;
}
public ResponseEntity<Collection<HpManifest>> getRecipes() {
logger.info("Retrieving recipes from");
UriComponentsBuilder builder =
UriComponentsBuilder.fromHttpUrl(endpointManifests)
.queryParam("type", HpManifestType.RECIPE.getType());
logger.info("REST endpoint: " + builder.toUriString());
ResponseEntity<Collection<HpManifest>> recipes = restTemplate.exchange(
builder.toUriString(),
HttpMethod.GET, null, new ParameterizedTypeReference<Collection<HpManifest>>() {});
logger.info("recipes are:");
recipes.getBody().forEach(r -> logger.info(r.toString()));
return recipes;
}
I ran into a similar issue just the other day. In my case it turned out to be that recipes (returned from the restTemplate.exchange method) contained a Transfer-Encoding: chunked in the headers and then when you return recipes, your spring framework is probably also including a Content-Length header. The combination of these two headers in a response to a browser can cause issues because the browser thinks it's getting chunked data back, but in reality it is not. I suggest making a new ResponseEntity from your recipes variable along the lines of:
return ResponseEntity.status(recipes.getStatusCode()).body(response.getBody());
Alternatively you could maybe force your spring framework to return chunked data, but I think that is not the right way to go.

GWT JSONPRequestBuilder - "Unknown Token :" error in browser console with Timeout exception at the end

I am trying to call a Restful WS from GWT using JSOPRequestBuilder. I have a similar issue which was reported in the link
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/ef93383aca7a3dfc/d4dc5bad1a9110ea
But, I could not figure out the solution. Kindly help me at the earliest.
My JAX-WS resource code snippet from server
#GET
#Produces(MediaType.APPLICATION_JSON)
public DealerAddress getDealerAddress(#QueryParam("dealerId") String sDealerId) {
DealerAddress dlrAd = new DealerAddress("test", "test", "test", "test", 10, new Date(), new Date());
return dlrAd;
}
Jersey returns a JSON object of DealerAddress.
Now rest URL "https://127.0.0.1:8181/application/rest/OrderManagementResource?alt=json-in-script&dealerId=DLR1"
works absolutely fine when i tried request in browser.
It even works with RequestBuilder approach from GWT but not with JSONPRequestBuilder approach.
Code snippet to invoke WS from GWT using JSONPRequestBuilder
JsonpRequestBuilder jsonPReqBuilder = new JsonpRequestBuilder();
jsonPReqBuilder.setTimeout(100000);
jsonPReqBuilder.setCallbackParam("callback");
jsonPReqBuilder.requestObject("https://127.0.0.1:8181/application/rest/OrderManagementResource?alt=json-in-script&dealerId=DLR1" , new AsyncCallback<DealerAddressJSON>() {
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
caught.printStackTrace();
Window.alert("Inside error"+caught.getLocalizedMessage());
}
#Override
public void onSuccess(DealerAddressJSON result) {
// TODO Auto-generated method stub
Window.alert("Inside success"+result);
}
});
where as DealerAddressJSON is a JavaScriptObject type class.
I could see that my JAX Rest resource getting called and saying returning from server.
Also, I could see that in Firebug that the response comes in browser but fails with an exception "Unknown token :"
At the end I always get a Timeout exception.
Now I am in big question whether the way we return JSON from JAX-RS resource is a problem in server
or
JSONPRequestBuilder calling procedure is a problem? I could not understand the callback changes which some of the links explained on this issue.
Kindly help me.
You are probably sending back JSON, while the JSONPRequestBuilder expects JSONP. These are not the same thing.
JSON is just the data, as is - make the request using AJAX (i.e. the RequestBuilder), and the contents can be read directly. These requests can only be made to the same server. Example JSON data:
{"response":"success", "items":[{"id":1}, {"id":2}]}
In contrast, JSONP is designed for cross-origin requests, so instead of just containing the data, the data is wrapped up in a JavaScript. Since your JSON service isn't wrapping the a response in a js function call, this isn't working. Example JSONP data:
callback_1({"response":"success", "items":[{"id":1}, {"id":2}]})
The callback changes with each request, so the server is supposed to change that callback function based on what the client requested each time.

GWT - Way around Access-Control-Allow-Origin?

I'm making an internet application with GWT, and one of the features that I've been stuck on for a few weeks is getting the users contact data from google data. I've tried things like GWT-GData and they don't seem to play nicely with the current version of GWT, so I tried going the more traditional approach with OAuth and doing an HTTP Get request. I haven't been receiving anything back as a response, and couldn't figure out why, and I happened across my javascript error log and I'm getting:
"Origin [site name here] is not allowed by Access-Control-Allow-Origin"
I've done some reading and I have a decent idea of what's going on, but I don't know how to get around it in GWT. I've found plenty of read-ups on how to get around it with other platforms, but I haven't seen anything for GWT. Can anyone offer any wisdom?
Edit:
Here is the code I'm using:
public static void doGet(String url, String oauthToken) {
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
try {
Request request = builder.sendRequest(oauthToken, new RequestCallback() {
#Override
public void onError(Request request, Throwable e) {
GWT.log(e.toString(), e);
}
#Override
public void onResponseReceived(Request request, Response response) {
Window.alert("HEADER:" + response.getHeadersAsString()
+ "\nSTATUS: " + response.getStatusText()
+ "\nTEXT: " + response.getText());
}
});
} catch (RequestException e) {
GWT.log(e.toString(), e);
}
}
There's nothing you can do but configure the server to accept the origin of the request (i.e. add it to the returned Access-Control-Allow-Origin.
Because it's GData, it might however simply be a mistake on your side re. the requested URL: there's no Access-Control-Allow-Origin when you request data in Atom format, only when requesting JSON (and the value is then * which allows everyone, so shouldn't cause any issue like you're seeing): http://code.google.com/p/chromium/issues/detail?id=45980#c2
While this doesn't answer the original question, the following may help others who have the same underlying issue that arrived at this page (I'm using a GWT client with a Groovy web server). This did the trick on the server:
HttpExchange.getResponseHeaders().add("Access-Control-Allow-Origin","*");

gwt: making remote calls fails - sop?

I am writing some interface for users to collect data and send to a server. I went for GWT for various reasons.
Now, when I try to call my server:
String url = "http://127.0.0.1:3000/data/collection.xml";
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
Request request = builder.sendRequest(data, new RequestCallback() {
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
result.setText("SUCCESS!");
} else {
result.setText("ERROR with code: " + response.getStatusCode());
My server gets the request (a POST with some data) but I get ERROR with code: 0 (!) all the time. I guess this has to do with SOP. I read lots about this SOP but I am even more confused now. I tried to follow this tutorial but that's using a different approach (I managed to adapt it to issue GET calls only, but return objects are always null).
Can anyone point me into the right direction? thanks
You can not call any service from another server because of SOP. What you can do, you can use your original server as proxy to other servers.. I would recommend you to read this tutorial.

How to fix Jersey POST request parameters warning?

I'm building a very simple REST API using Jersey, and I've got a warning in my log files that I'm not sure about.
WARNING: A servlet POST request, to
the URI
http://myserver/mycontext/myapi/users/12345?action=delete,
contains form parameters in the
request body but the request body has
been consumed by the servlet or a
servlet filter accessing the request
parameters. Only resource methods
using #FormParam will work as
expected. Resource methods consuming
the request body by other means will
not work as expected.
My webapp only has the Jersey servlet defined, mapped to /myapi/*
How can I stop these warnings?
For me the warning was showing for POST application/x-www-form-urlencoded. And I am using Spring Boot which has an HiddenHttpMethodFilter that does a getParameter before anything else... So I ended up doing this nasty override:
#Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new HiddenHttpMethodFilter() {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if ("POST".equals(request.getMethod())
&& request.getContentType().equals(MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
filterChain.doFilter(request, response);
} else {
super.doFilterInternal(request, response, filterChain);
}
}
};
}
This message is meant to warn developers about the fact that the request entity body has been consumed, thus any other attempts to read the message body will fail.
It is safe to ignore the message or filter it out from the logs:
java.util.logging.Logger jerseyLogger =
java.util.logging.Logger.getLogger(WebComponent.class.getName());
jerseyLogger.setFilter(new Filter() {
#Override
public boolean isLoggable(LogRecord record) {
boolean isLoggable = true;
if (record.getMessage().contains("Only resource methods using #FormParam")) {
isLoggable = false;
}
return isLoggable;
}
});
The following thread describes the warning you are receiving. It sounds as though you might have a filter defined in your web.xml that is processing the request before Jersey does.
Finally got rid of this by making sure I had Content-Type: application/json in my request headers (obviously, on the client side)
I just had my ajax-function in JQuery set to contentType: "application/x-www-form-urlencoded; charset=UTF-8" because with a prior solution (without Jersey) I had some encoding problems. When I removed that the message was gone and everything worked fine.
This warning is the only thing the WebComponent logs, so just turn logging up to ERROR level or turn off logging for this component in your logback.xml or wherever you have logging configured. You don't need to write a custom filter to ignore this specific message since there are no other messages logged from this component.
Source code snippet from org.glassfish.jersey.servlet.WebComponent version 2.14:
if(!form.asMap().isEmpty()) {
containerRequest.setProperty("jersey.config.server.representation.decoded.form", form);
if(LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, LocalizationMessages.FORM_PARAM_CONSUMED(containerRequest.getRequestUri()));
}
}
The localized message that is used for this warning message is:
form.param.consumed=A servlet request to the URI {0} contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
Turn logging off for the WebComponent in your logback.xml like so:
<logger name="org.glassfish.jersey.servlet.WebComponent" level="OFF" additivity="false"/>
Right.
So I've been suffering this issue, and I've been trying to solve it on different ways, but I did't want to change my web.xml settings, just because if I was testing my application with Postman it worked perfect, but when it was being integrated with the webapp it fails with the mentioned issue (A servlet request to the URI {MY_URI} contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.)
So as #clijk mentioned, you only have to set your headers as:
"Content-Type":"application/json"
"charset":"UTF-8"
and voilá, the warning it's gone.
Thanks
In my case I've fixed this error when I've changed the Object Date to String in the method.
Error:
#POST
#Path("/myPath")
#Produces(MediaType.APPLICATION_JSON)
public List<MyObject> myMethod(#FormParam("StartDate") Date date) throws Exception {
Fixed
#POST
#Path("/myPath")
#Produces(MediaType.APPLICATION_JSON)
public List<MyObject> myMethod(#FormParam("StartDate") String date) throws Exception {
Put this to your resource signature. Or find this string in your project someone already use this if #PUT or #POST is used. This should help
import javax.ws.rs.Consumes;
#Consumes(MediaType.APPLICATION_JSON)