GWT RPC fails when launching app from different urls - gwt

I'm using urls to navigate to different screens inside my GWT app. For example:
http://127.0.0.1/home
http://127.0.0.1/info/contact-us
http://127.0.0.1/app/index.html
I have a servlet that serves the html containing the required script element for GWT (my GWT module name is "app"):
<script type="text/javascript" language="javascript" src="/app/app.nocache.html">
</script>
This is working great with GWT 2.6.1. In the browser dev tools it's possible to see that RPC calls are made to my RemoteService at http://127.0.0.1/app/rpc
The problem is when I upgraded to GWT 2.8, my app's RPC call endpoint is now different and wrong, depending on the URL used. For example:
http://127.0.0.1/home -> http://127.0.0.1/rpc
http://127.0.0.1/info/contact-us -> http://127.0.0.1/info/rpc
http://127.0.0.1/app/index.html -> http://127.0.0.1/app/rpc
For the above URLs the module is always correctly loaded and executed, however RPCs fail in the first two cases. only the last URL allows my app to make RPC calls.
The RPC endpoint can be set by casting the client-side service proxy to ServiceDefTarget and using setServiceEntryPoint(). As follows:
ourInstance = (MyRemoteServiceAsync)GWT.create(MyRemoteService.class);
ServiceDefTarget serviceDefTarget = (ServiceDefTarget) ourInstance;
serviceDefTarget.setServiceEntryPoint("/app/rpc");
However, the request payload still contains a reference to the incorrect module base. The http headers sent on the RPC request have incorrect values also:
X-GWT-Module-Base:http://127.0.0.1/foo/bar/
Is there a way to force the client's RPC mechanism to use the correct RPC URL /app/rpc? Or perhaps a way to set the module-base correctly?
UPDATE 1
Seeing the same behaviour in GWT 2.7.
Also, when deployed in a WAR the <module-hash>.cache.js file doesn't load because it is also requested relative to the url. This is very bad because it means that the module code won't be cached, since this url is different every time. The fix needs to be made in the selector <module>.nocache.js. Is anyone actually using GWT with url linking in the real world?

By specifying a <meta> element in the <head> element of the html document, the bootstrap nocache.js selector javascript will choose the correct module baseUrl. The baseUrl must be a fully-specified absolute url, and end with a /.
For my example, the exact element was:
<head>
...
<meta name="gwt:property" content="baseUrl=http://127.0.0.1/app/" />
...
</head>

Related

Mailchimp No Host Exception when Subscribing Email to A List

I'm trying to send a subscription call, but got an error saying the the URL is invalid.
This is the URL I used:
https://us14.api.mailchimp.com/3.0/lists/<list-id>/members/
then I get this back in the response:
<HTML>
<HEAD>
<TITLE>Invalid URL</TITLE>
</HEAD>
<BODY>
<H1>Invalid URL</H1>
The requested URL "http://%5bNo%20Host%5d/3.0/lists/41e44e1bde/members/", is invalid.
<p>
Reference #9.cc6a1db8.1483891456.16189371
</BODY>
</HTML>
which translates to:
http://[No Host]/3.0/lists/<list-id>/members/
us14 is definitely the right data center according to the documentation so I'm not quite sure what's wrong.
It turned out that if you set HTTP header field "Host" in the request, it will always return this error. I tested this out by removing every fields one-by-one and this was the only one that caused an issue.
Many environments use the Host header for stuff like virtual sites where you are running more than one website behind the same IP Address (i.e. api.mailchimp.com and www.mailchimp.com could be on the same server) It is definitly possible for an error to be received if you set an invalid host since their proxies can't route it correctly. Normally, the host header is set automatically by the browser or HTTP client and usually not something you would override.
Are you still having trouble? If so, would be useful to see a screenshot of something like PostMan or https://ApiRequest.IO to see what your inputs are.

Errai and portlet deployment

This is my first question, for which I didn't find any answers in the web. The problem is, when using errai in portal environment, you'll get Exceptions on server side like this:
/out.50694-4048.erraiBus generates exception: null
and on client side like this:
GET http://myserver:8080/user/admin/in.20679-27603.erraiBus?z=1 404 (Not Found)
GET http://myserver:8080/user/admin/in.20679-27603.erraiBus?z=2 404 (Not Found)
GET http://myserver:8080/user/admin/in.20679-27603.erraiBus?z=3 404 (Not Found)
The reason for this is, that errai calls urls which are relative to the gwt module and not the web context name. Solution follows.
Same problems on other forums:
http://www.liferay.com/de/community/forums/-/message_boards/message/12383627?_19_threadView=flat
https://community.jboss.org/thread/177590?start=0&tstart=0
You need to add a script in the html host page, like described in Client Configuration in the errai docu.
<script type="text/javascript">
erraiBusApplicationRoot = "/MyWebContextName";
</script>
This will solve all errai communication problems.

GWT Async to URL

I'm using GWT to develop a web app. I'm currently using AJAX calls to retrieve values from the server. I have following queries regarding to AJAX calls:
Assume: I have an app, name of which is: "Application" and the entry point class is: "entry.java"
I know: the application could be invoked as: http://localhost:8080/Application/entry.html
1. I would like to know what what is the output URL given by gwt.getmodulebaseURL()?
Assume: In the same application I have a service called "ServerValuesService" and its corresponding Async. I have corresponding serviceImpl, which has a method called List < String >search(String) at the server side.
I could retrieve the values from the server as well. However,
2. I would like to know what would be the direct URL to access this service? For Instance, I need to obtain the list of values, by just giving a URL (passing value for the String). i.e. I need to access the method search(String) and retrieve the list just by typing a url such as:
http://localhost:8080/Application/entry/serverValuesService?string="hello"
I'm sure the above URL is wrong. I need to know exact conversion between URL and the corresponding service. Is this possible at all?
Thanks in advance!
1) In your case it will give you http://localhost:8080/Application . Application is your modulename.
2) These services are actually HttpServlets and their URL's are defined in the web.xml file. But Google uses POST method to send your variables and takes care of serialization for you, what you are trying to do is send it via GET method which is as far as I know not implemented by Google RemoteServiceServlet.So I would say no its not possible unless you extend these services to work with GET methods yourself but I don't know if that is possible.
Assume: I have an app, name of which is: "Application" and the entry point class is: "entry.java"
I know: the application could be invoked as: http://localhost:8080/Application/entry.html
The url http://localhost:8080/Application/entry.html is called host page url. In this html page you load your GWT module using a script tag:
<!-- This script tag is what actually loads the GWT module. The -->
<!-- 'nocache.js' file (also called a "selection script") is -->
<!-- produced by the GWT compiler in the module output directory -->
<!-- or generated automatically in hosted mode. -->
<script language="javascript" src="calendar/calendar.nocache.js"></script>
So if you put above example in your entry.html, the module will be loaded from http://localhost:8080/Application/calendar/calendar.nocache.js making http://localhost:8080/Application/calendar/ your module base url.
I would like to know what would be the direct URL to access this
service? For Instance, I need to obtain the list of values, by just
giving a URL (passing value for the String). i.e. I need to access the
method search(String) and retrieve the list just by typing a url
GWT RPC use a custom serialization format to encode requests to the RPC Service on server. The RPC service is implemented as a subclass of RemoteServiceServlet on the server. The RemoteServiceServlet handles the http POST requests, de-serializing the request from client and invvoking appropriate service method of sub-class.
So for directly accessing the service you'll need:
1. The service URL
2. Request payload encoded in GWT's custom serialization format
3. Ability to HTTP POST the payload to the Service URL
1 and 3 are easy to acquire. You already know the URL at which your service is mapped in web.xml. And you can do post from any http client or browser plugins like this. The hard-part would be to generate request payload in GWT's custom serialization format. For simple cases, you can generate a request from your application and capture the raw payload from Firebug, Fiddler or similar tool and simply replay it using your http client.

GWT JSONP with Post not Get

I have a web service in the form `http://....../methodName
It returns a jsonp result such as:
methodName(["a":"a", "b":"b"])
GWT provides JsonpRequestBuilder class to parse jsonp.
JsonpRequestBuilder rb = new JsonpRequestBuilder();
rb.setCallbackParam("callback");
rb.requestObject("http://...../methodName", new AsyncCallback<TestJS>(){
...
});
This structure makes a request to url :
"http://...../methodName/?callback=__gwt_jsonp_P0.onSuccess".
My web service returns a callback with methodName not with __gwt_json.....
So gwt could not create a JavaScriptObject from that response.
Also JsonpRequestBuilder works with GET not POST.
How can I achieve those: Sending requests with POST and modifying GWT's default callback name.
JSONP will NOT work with POST. Its not a GWT limitation btw.
JSONP is essentially including a javascript file from your server. So, when you make a JSONP call, a temporary tag is added to the DOM.
Now, a <script> tag can always makes a GET request. That's a browser thing, and GWT cannot do much about it.
If you want to make a cross-domain POST call, you have to chose from one of the following options (and they have nothing to do with GWT)
Use Flash plus a crossdomain.xml that allows cross domain posts
Use Cross Origin Resource Sharing, or CORS. NOTE that this is only supported in modern browsers
Use a proxy server on your domain
Unfortunatly, this isn't how JsonP works. The requests are made by adding a tag to the page, and the results are passed into a function wrapped around the data – in your case, __gwt_jsonp_P0.onSuccess.
The callback name can't be affected, at least while using JsonpRequestBuilder – the system needs to account for the fact that you could send multiple requests out at once, possibly even to different endpoints. A JsonP endpoint that doesn't allow the caller to customize the callback function name is very unusual, and even more odd is an endpoint expecting JsonP calls that expects an impossible POST.
You can implement your own JsonP client side code by using the ScriptElement type, and registering your own global callback to call into your GWT java code.
Look into the API docs for the web service, and see if there is perhaps a better way to communicate with it, perhaps by using a proxy on your own server, avoiding the cross domain issue altogether.

Force the browser to send some HTTP request header

I need to include some secure (BASIC authentication) application.
when I open the application URL in the browser, the browser asks me to enter your credentials ...
what I know is that:
The browser ask the server to get
some URL -- the url of the app
The server checks the request header
for the Authentication header and
didn't find it
The server sends 401 to the
browser back
The browser interpret this response
code into a message dialog that
shows to me asking me to enter the
username/password to send back to
the server in the Authentication
request header
So far... so good, I can write some page (in JSP) that send this required http request header to the request that is calling this page..
So I'll call this application through my page..
The problem here is, this application (in fact a GWT application) contains a reference to some Javascript and CSS files that is coming from the server that hosts this application. the application page that I import looks like:
<html>
<link href="http://application_host/cssfile.css" />
<link href="http://application_host/javascriptfile.js" />
.....
</html>
So, again I found the application asks me for the authentication crenditals for the css and js files!
I am thinking of many solutions but don't know the applicability of each
One solution is to ask the browser
(via Javascript) to send the request
header (Authentication) when he
asks the server for the js and css
files
please give me your opinions about that... and any other suggestions will be very welcomed.
Thanks.
I think you're running into some weirdness with how your server is configured. Authentication happens in context of a authentication realm. Your assets should either be in the same authentication realm as your page, or (more likely) should not require authentication at all. The browser should be caching credentials for the given realm, and not prompt for them again.
See the protocol example on http://en.wikipedia.org/wiki/Basic_access_authentication
Judging from your story, something tells me your problem is with the authentication method itsef. Not how to implement it. Why do you want to bother with the request header so much?
As far as i know, you can configure your container (ie Tomcat) to force http authentication for certain urls. Your container will make sure that authentication has taken place. No need to set http headers yourself whatsoever.
Perhaps you can explain a bit better what you are trying to achieve, instead of telling implementation details?
Why css & js files are kept in protected area of server? You need to place files into public area of your server. If you don't have public area, so you nead to prpvide for it. how to do it depends from serverside software architecture & configuration.