GWT SuperDevMode RPC host - gwt

I'm trying to start SuperDevMode the following way. I modified my index.jsp page to append a configurable prefix to the .nocache.js file. Production config contains an empty prefix, while development config contains something like http://localhost:9876. Then I start the server on Tomcat and type localhost:8080. GWT starts normally, but when it tries to send an RPC request, it fails, because request goes to localhost:9876 instead of localhost:8080. How can I customize which host should RPC use to send request to?

I spent some time digging into GWT code with Eclipse and debugger, and found, that GWT RPC concatenates the result of GWT.getModuleBaseURL() with the value of #RemoteServiceRelativePath. Here is the code of the getModuleBaseURL method:
public static native String getModuleBaseURL() /*-{
// Check to see if DevModeRedirectHook has set an alternate value.
// The key should match DevModeRedirectHook.js.
var key = "__gwtDevModeHook:" + $moduleName + ":moduleBase";
var global = $wnd || self;
return global[key] || $moduleBase;
}-*/;
I also examined dev_mode_on.js and found several occurences of __gwtDevModeHook, but none of them contained moduleBase. Also dev_mode_on.js install all its hooks into sessionStorage, while getModuleBaseURL reads from $wnd (I used debugger and became convinced that $wnd = window).
So I used the following solution and it worked for me. I simply added the following into my index.jsp:
<c:if test="${not empty gwtScriptPrefix}">
<script type="text/javascript">
window["__gwtDevModeHook:MYAPP:moduleBase"] = "MYAPP/";
</script>
</c:if>
just before
<script type="text/javascript"
src="${gwtScriptPrefix}MYAPP/MYAPP.nocache.js">
</script>
where the gwtScriptPrefix attribute is calculated by System.getProperty, and the corresponding system property is set to localhost:9876/ on the Eclipse running configuration.

Related

Correct Way To Use CSP Filter In Play 2.7

I am trying to define the CSP policy for my web service and am using the new features in Scala Play 2.7.
This is what I have done:
Set the CSP directive and nonce configuration in my application.conf
csp {
nonce {
enabled = true
pattern = "%CSP_NONCE_PATTERN%"
header = false
}
directives {
base-uri = "'none'"
object-src = "'none'"
script-src = ${play.filters.csp.nonce.pattern} "'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http:"
}
}
In the Twirl template I make reference to the nonce as follows:
<script #{CSPNonce.attr}...</script>
<script #{CSPNonce.attr} ..</script>
A couple of observations:
According to the documentation, if I switch on csp.header = true in the application.conf, I should see the nonce value in the RequestHeader which is implicitly brought into the Twirl template. I don't see this header at all when I print out the the header values.
Similarly, I don't see the nonce value in the script tags when I view the generated HTML in my browser.
Irrespective of whether I add the #{CSPNonce.attr} Twirl snippet in my inline script code, the inline JS gets loaded. This is strange as I thought only inline scripts marked with the correct nonce would only be allowed to load.
So what is the deal here? Am I not using this feature correctly?
I suspect that you have not enabled the filter.
Please check that you have added
play.filters.enabled += play.filters.csp.CSPFilter
to your application.conf.
You're also using csp instead of play.filters.csp in your configuration example, so that could be an issue as well.
There is a test specification with HOCON settings that you can check configuration against.
https://github.com/playframework/playframework/blob/2.7.x/web/play-filters-helpers/src/test/scala/play/filters/csp/CSPFilterSpec.scala#L69
I can confirm the CSP with a nonce feature works, including this header which shows as X-Content-Security-Policy-Nonce when the CSPFilter is enabled and play.filters.csp.nonce.enabled is true and play.filters.csp.nonce.header is true. Don't forget to restart sbt after the config changes here.
When you inspect the html with the Firefox DOM inspector, part of the developer tools, the nonces show as empty strings. Have you tried using Right Click > View Source to see if the nonce is in the unprocessed raw html?
Everything seems to be whitelisted by the browser until you specify the nonce in the CSP, which can be done like this: play.filters.csp.directives.script-src = ${play.filters.csp.nonce.pattern} "'self' 'unsafe-inline' 'unsafe-eval'" and the play.filters.csp.nonce.pattern is %CSP_NONCE_PATTERN%.

Reverse routing on an application deployed in a Tomcat context

I am developing a Play 1.2.5 application that will be installed in a Tomcat context:
http://mytomcat:8080/myapp
And in my routes file I have:
GET /companies/{companyID}/employees Employees.getForCompany
As per the instructions for deploying a Play application in a Tomcat context, I am generating URLs exlusively using the Reverse Router. This works fine, but I am not sure what to do in the case of a jQuery method such as an Ajax request of this style:
var companyID = $('#companies').find(":selected").val();
$.ajax({
url : "#{Employees.getForCompany(companyID)}",
...
});
Obviously the value of companyID isn't known at the time of the generation of the HTML and the resolution of routes by the reverse router.
The only solution that I can see is to reconfigure my routes file so that the URLs are different and the parameters are always at the end, but that makes the REST URLs less logical.
GET /companies/employees/{companyID} Employees.getForCompany
Is there a better way?
I have found the solution myself - Play includes the jsAction tag which generates a function that builds the correct URL:
var companyURL = #{jsAction #Employees.getForCompany(':companyID') /}
$.ajax({
url : companyURL({companyID:companyID}),
...
});
Like that I can maintain the preferred routes mapping:
GET /companies/{companyID}/employees Employees.getForCompany

Making a POST request in Selenium without filling a form?

I have an application A that should handle a form submit made with POST method. The actual form, that initiates the request, is in totally separate application B. I am testing application A using Selenium, and I like to write a test case for form submit handling.
How to do this? Can this be done in Selenium at all? Application A does not have a form that can initiate this request.
Note, that the request must use POST, otherwise I could just use WebDriver.get(url) method.
With selenium you can execute arbitrary Javascript including programmatically submit a form.
Simplest JS execution with Selenium Java:
if (driver instanceof JavascriptExecutor) {
System.out.println(((JavascriptExecutor) driver).executeScript("prompt('enter text...');"));
}
and with Javascript you can create a POST request, set the required parameters and HTTP headers, and submit it.
// Javascript example of a POST request
var xhr = new XMLHttpRequest();
// false as 3rd argument will forces synchronous processing
xhr.open('POST', 'http://httpbin.org/post', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send('login=test&password=test');
alert(xhr.response);
In modern bleeding edge browsers you can also use fetch().
If you need to pass over to selenium the response text then instead of alert(this.responseText) use return this.responseText or return this.response and assign to a variable the result of execute_script (or execute_async_script) (if using python). For java that will be executeScript() or executeAsyncScript() correspondingly.
Here is a full example for python:
from selenium import webdriver
driver = webdriver.Chrome()
js = '''var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://httpbin.org/post', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send('login=test&password=test');
return xhr.response;'''
result = driver.execute_script(js);
result will contain the return value of your JavaScript provided that the js code is synchronous. Setting false as the third argument to xhr.open(..) forces the request to be synchronous. Setting the 3rd arg to true or omitting it will make the request asynchronous.
❗️ If you are calling asynchronous js code then make sure that instead of execute_script you use execute_async_script or otherwise the call won't return anything!
NOTE: If you need to pass string arguments to the javascript make sure you always escape them using json.dumps(myString) or otherwise your js will break when the string contains single or double quotes or other tricky characters.
I don't think that's possible using Selenium. There isn't a way to create a POST request out of nothing using a web browser, and Selenium works by manipulating web browsers. I'd suggest you use a HTTP library to send the POST request instead, and run that alongside your Selenium tests. (What language/testing framework are you using?)
The easiest way I found is making an intermediary page solely for the purposes of submitting a POST request. Have selenium open the page, submit the form, and then get the source of the final page.
from selenium import webdriver
html='<html><head><title>test</title></head><body><form action="yoursite.com/postlocation" method="post" id="formid"><input type="hidden" name="firstName" id="firstName" value="Bob"><input type="hidden" name="lastName" id="lastName" value="Boberson"><input type="submit" id="inputbox"></form></body></html>'
htmlfile='/tmp/temp.html'
try:
with open(htmlfile, "w") as text_file:
text_file.write(html)
except:
print('Unable to create temporary HTML file')
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Firefox()
driver.get('file://'+htmlfile)
driver.find_element_by_id('inputbox').click();
#wait for form to submit and finish loading page
wait = WebDriverWait(driver, 30)
response=driver.page_source

Integrating Google Analytics into GWT application

This should be totally simple but I can't get it working no matter what I try. I'm trying to use Google Analytics with GWT application. From what I understood, there are two way to do it:
First is synchronous, by inserting tracking code at the end of <head> section HTML page and then calling this method:
public static native void recordAnalyticsHit(String pageName) /*-{
pageTracker._trackPageview(pageName);
}-*/;
Second is asynchronous, by inserting tracking code just after <body> tag and then calling this method:
public static native void recordAnalyticsHit(String pageName) /*-{
_gaq.push(['_trackPageview(' + pageName + ')']);
}-*/;
When running each of those methods, however, I get this exceptions in hosted mode:
[ERROR] [myproject] Uncaught exception escaped
com.google.gwt.core.client.JavaScriptException: (ReferenceError): pageTracker is not defined
[ERROR] [myproject] Uncaught exception escaped
com.google.gwt.core.client.JavaScriptException: (ReferenceError): _gaq is not defined
When observing site in Firebug, I see that ga.js gets loaded, but that's about it.
Did anyone get Analytics working with GWT? Also, does _gaq accept page name as trackPageview parameter, since all the examples I've seen use this call:
_gaq.push(['_trackPageview()']);
(Of course, that also doesn't work for me.)
This is just a guess, but you probably need to reference the host page (the one where the Google Analytics JS code has been included) via $wnd in the JSNI, like this:
public static native void recordAnalyticsHit(String pageName) /*-{
$wnd.pageTracker._trackPageview(pageName);
}-*/;
JSNI code (and in general, GWT code) is run in a iframe to keep the namespace clean, that's why you need the $wnd reference to the main window.
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-xxxxxx-x");
pageTracker._trackPageview("/subdirectory/pagename");
</script>
See http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55485 for details.

Count active sessions in J2EE app deployed on JBoss 3.2.1

I manage a J2EE application which is deployed on JBoss 3.2.1. As part of my service to my client I want to provide reports which show the number of active sessions. I have implemented a simple class and a JSP page which retrieve the number of active sessions, but I have discovered a flaw: the process of checking the number of sessions itself creates a new session, and therefore inflates the number of sessions.
Here is the code for my class:
package com.hudsongates;
import javax.servlet.http.*;
public class SessionCount implements HttpSessionListener
{
private static int numberOfSessions = 0;
public void sessionCreated (HttpSessionEvent evt)
{
numberOfSessions++;
}
public void sessionDestroyed (HttpSessionEvent evt)
{
numberOfSessions--;
}
// here is our own method to return the number of current sessions
public static int getNumberOfSessions()
{
return numberOfSessions;
}
}
The JSP page looks like this:
<html>
<head>
<title>Active Sessions</title>
</head>
<body>
activeSessions=<%=com.hudsongates.SessionCount.getNumberOfSessions()%>
</body>
</html>
I would like to change the approach slightly so that instead of using a JSP page, I use a simple batch file. For example, I created a batch file called getSessions.bat:
REM Setup environment
call environment.bat
set LOG_PATH=%INSTALL_PATH%\log
set =%INSTALL_PATH%\lib\app.jar
set CLASSPATH=%INSTALL_PATH%\lib\app.jar
%JDK_HOME%\bin\java -cp "%CLASSPATH%" com.hudsongates.SessionCount.getNumberOfSessions() > %LOG_PATH%\test.log
The problem is that when I execute the batch file I get the following exception:
Exception in thread "main" java.lang.NoClassDefFoundError: com/hudsongates/SessionCount/getNumberOfSessions()
Do I need to add a "main" method to my class? If so, what would it do? Is there a better way of achieving my end goal of accurately counting the number of active sessions? Bear in mind that the session count needs to be written to a log file in the following format:
activeSessions=24
Thanks in advance,
Paul
Two possibilities spring to mind:
Your JSP can be configured to not create a new session. Stick this at the top of your JSP:
<%# page session="false"%>
Alternatively, write a JMX MBean which implements JBoss's ServiceMBean interface, and deploy it as a JBos service. This MBean would query the session count, and would appear on JBoss's JMX console. You can use your web browser to monitor it from there, without interfering with your session count.
The JBoss JMX Console already has a integrated session counter in host=localhost,path=/YOUR_PROJECT,type=Manager
By the way, you should use AtomicInteger or synchronize to take care of concurrency problems.