GWTTestCase file upload - gwt

I am trying to write some gwt testcases to upload files using FileUpload and FormPanel.
My code (unttested) looks like:
#Test
public void testImportXml() {
delayTestFinish(10000);
FormPanel fileForm=new FormPanel();
fileForm.setEncoding(FormPanel.ENCODING_MULTIPART);
fileForm.setMethod(FormPanel.METHOD_POST);
fileForm.setAction(GWT.getModuleBaseURL()+"/xmlupload");
URL myFile=this.getClass().getClassLoader().getResource("myfile.xml");
// FileUpload uploadField; ??
fileForm.addSubmitHandler(new SubmitHandler() {
#Override
public void onSubmit(SubmitEvent event) {
logger.info("submit handler pushed");
}
});
fileForm.submit();
}
I could not find a method to configure FileUpload to use "myFile".
I understood that this is done for browser-security reasons, but it is a massive obstacle when writing testcases.
Does there exist a way to specify filenames for FileUpload for testcases within gwt?

No.
But then one could wonder what is it that you're actually trying to test?
the submit / submit-complete handlers? You'd better fire the events directly at the FormPanel; you could also refactor your code to use some MV* pattern so that the code you're actually testing is not tied to GWT widgets, then you can use a vanilla JUnit test.
the servlet? Then don't use a GWTTestCase, use HttpClient or anything similar and make a request against your servlet, running in a server (best done as an integration test; have a look at Arquillian to make it easier to setup)
the whole interaction between the FormPanel+FileUpload and servlet? Then don't use a GWTTestCase, use Selenium to drive a browser talking to a running server (best done as an integration test or acceptance test)

Related

Strategies for implementing a user specific - custom content EntryPoint in GWT

We have developed a dashboard in GWT that contains some custom widgets for displaying customer's data in various graphical forms. We now want to move to a more custom / user specific approach where each customer who logs into the dashboard can see a different perspective of the dashboard. Some widgets will be available for some users, for some others not and with different initialization parameters.
We are trying to find an efficient strategy to do this. A potential solution would be to have the client side request all this information during EntryPoint loading and then use that incoming configuration to build itself and make further requests for the data. A more efficient solution would also allow downloading to the browser only those widgets relevant to the user.
Does GWT have any design pattern for this scenario? If not, what would a good high level solution be for this case?
Thank you.
Yes there is atleast one mechanism that can be useful to achieve your requirements
Code Splitting :- The idea is to split the particular section of code and download it in independent async call. Using this approach you can reduce the size of primary javascript file making initial page load faster. This approach allow GWT to skip inclusion of all those widgets which have references only inside GWT.runAsync() method in primary js file. Such widgets and code gets downloaded when application runs that code in independent call. you can use this approach and avoid download of additional dashboard charts based on some conditions like user type and so. Here is sample code from GWT reference website
public class Hello implements EntryPoint {
public void onModuleLoad() {
Button b = new Button("Click me", new ClickHandler() {
public void onClick(ClickEvent event) {
GWT.runAsync(new RunAsyncCallback() {
public void onFailure(Throwable caught) {
Window.alert("Code download failed");
}
public void onSuccess() {
Window.alert("Hello, AJAX");
}
});
}
});
RootPanel.get().add(b);
}
}

How to include 3rd party JavaScript libraries in a reusable gwt library/widget?

I'm trying to get my feet wet with GWT to see if migrating will work out. I usually try the more difficult parts first to make sure I can finish the project. The most difficult part of my project(s) is referencing 3rd party JS libs. In this example I'm trying to use PubNub as much of our platform uses it.
What I'd like to do is create a reusable object that can be used in other GWT projects in need of PubNub. I've got a simple little test running successfully (ie, I've got the basics of JNSI working), but my question is -> where do I put the reference to the 3rd party script in order to create the library/module properly?
Right now I just put the reference to the external scripts in the HTML page in the project, but I'm pretty sure this is incorrect from a reusability perspective, as this lib would be used in other projects, each of which would have their own base HTML page.
I tried putting the reference in the gwt.xml file, but this seems to lose the references (ie my test project no longer works as it did when the scripts were in the HTML page)
Do you have any tips on how to include 3rd party libraries in a reusable GWT library/widget?
Here you have an example using client bundles and script injector, you can use either synchronous loading or asynchronous.
When using sync the external js content will be embedded in the application, otherwise it will be include in a different fragment which will be got with an ajax request.
You can put your api in any server and load it with the ScriptInjector.
public class Example {
public static interface MyApiJs extends ClientBundle {
MyApiJs INSTANCE = GWT.create(MyApiJs.class);
#Source("my_api.js")
TextResource sync();
#Source("my_api.js") // Should be in the same domain or configure CORS
ExternalTextResource async();
}
public void loadSync() {
String js = MyApiJs.INSTANCE.sync().getText();
ScriptInjector.fromString(js).inject();
}
public void loadAsync() throws ResourceException {
MyApiJs.INSTANCE.async().getText(new ResourceCallback<TextResource>() {
public void onSuccess(TextResource r) {
String js = r.getText();
ScriptInjector.fromString(js).inject();
}
public void onError(ResourceException e) {
}
});
}
public void loadFromExternalUrl() {
ScriptInjector.fromUrl("http://.../my_api.js").inject();
}
}
[EDITED]
A better approach is to use a new feature in gwtquery 1.4.0 named JsniBundle. We introduced this feature during the GWT.create conferences at San Francisco and Frankfurt.
With this approach you can insert any external javascript (placed in your source tree or hosted in an external host) as a JSNI block. It has many benefits:
Take advantage of GWT jsni validators, obfuscators and optimizers.
Get rid of any jsni java method when the application does not use it.
The syntax is actually easy:
public interface JQueryBundle extends JsniBundle {
#LibrarySource("http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js")
public void initJQuery();
}
JQueryBundle jQuery = GWT.create(JQueryBundle.class);
jQuery.initJQuery();

Create a GWT RPC Service

I’m trying to create a backend for a homepage with GWT. I created a Google Web Application in Eclipse without sample code and now I would like to add the service, but the developer Google guide doesn’t help me. I’m not sure, where to add the interface and how it exactly works.
If I understand the google documentation correctly, I have to add a module and an entry point class, is that correct? It would be great if you could give me some tips and help how to create a rpc service.
If you create a new GWT project in the Eclipse "New Project" wizard, with "Generate project sample code" checked, it will include a fully functioning RPC service with a sample method, which you can then adapt or copy according to your needs.
Out of memory, don't have eclipse in front of me.
First do create a test project with generated testcode, you can delete it afterward.
Yes you will have to add a module.
Create in client the two interfaces for the async calls, inherit it on server side.
Hope I understood your question right.
I'm not sure what would help you the most. Google developer guide was enough for me (at least when I started using it on version 1.6) to create RPC services for my GWT application.
General APP
Module: is the .gwt.xml file. Yes, you'll need it. The GWT compiler will find it automagically and try to compile all the GWT code (the <source> element will tell which subpackage contains Java code that will be converted to JS). It will tell also which class implements the EntryPoint interface. The onModuleLoad will be the code executed when javascript runs in the client page.
RPC
Well, you should first try UI things and only then, when you're confident enough, try the server thing. Anyway the scheme is:
interface MyService extends RemoteService {
List<String> doSomething(String sample, int other);
}
#RemoteServiceRelativePath("../path/to/servlet") // see later
intercace MyServiceAsync {
void doSomething(String sample, int other, AsyncCallback<List<String>> callback);
}
These are the interfaces. Later is the async one. That's what you'll use from client side. Always calling and passing an implementation of AsyncCallback which will receive (sometime later, you don't know when) the result.
First interface is the syncrhonous one. That is what you need to implement on server. You must inherit from RemoteServiceServlet class (it is an implementation of servlet that already does all the values handling), and implement your interface. GWT code does the rest (almost).
public class ServiceImpl extends RemoteServiceServlet implements MyService
{
// implement the method normally
}
From client you'll need to create the service proxy:
private static MyServiceAsync MY_SERVICE = GWT.create(MyService.class);
Yes. I know it's weird how GWT knows MyserviceAsync and MyService work together. Don't worry about that. It works :)
Just use the service like this:
MY_SERVICE.doSomething("value", 111, new AsyncCallback<List<String>>() {
// note that this code executes some time in the future when response from server is back
public void onSuccess(List<String> result) {
Window.alert("Server answered with " + result.size() + " elements!");
}
public void onFailure(Throwable t) {
Window.alert("Server failed: " + t.getMessage());
}
}
Path to server
You'll have to configure your app to make that servlet implementation listen to URL indicated in #RemoteServiceRelativePath. That's the way client knows where to make the request, and the server knows which servlet attends that request. I'd suggest using:
../my-service.gwt as relative path (GWT module gets published in <ROOT>/module_name
and
configuring your web app to use the servlet for /my-service.gwt
But it's entirely upon your preferences :)
Anyway I think Google tutorials are the best. So please copy&paste. Try&modify until you get to understand the whole thing.

How to call a servlet from the viewImpl class in GWT?

I'm using GWT 2.4 with the MVP pattern, with uiBinder, and a widget: GwtUploader. When the user selects a file to upload and clicks a button, I need to make a call to a servlet. I'm not calling a service, I just need to access the HttpRequest so I can pull the file that the widget has uploaded, but I'm not clear how to do this?
Here is the uiHandler code:
#UiHandler("loadFileButton")
void onClickCalculate(ClickEvent e){
String fileName = fileUploader.getFileName();
...
The real answer is you don't. In MVP, the View should defer that kind of behavior to the Presenter, which ideally would defer it to some server-side handler. Check out this answer or this article for examples of how FileUpload can be used for this purpose. Since you mentioned you're using GWTUpload, try reading the Getting Started article.

Using GWT with SEAM

I want to use GWT with seam Framework, so i add the jar gwt-user-2.2.0.jar to my project. but when i invoke any method from the view (a xhtml page ) this exception is occured:
Caused by: java.lang.UnsupportedOperationException: ERROR: GWT.create() is only usable in client code! It cannot be called, for example, from server code. If you are running a unit test, check that your test case extends GWTTestCase and that GWT.create() is not called from within an initializer or constructor.
at com.google.gwt.core.client.GWT.create(GWT.java:92)
at com.google.gwt.user.client.ui.UIObject.(UIObject.java:188)
... 84 more
I use seam v2.2,I can post the code :
#Name("scheduleHandler1")
public class SheduleHandler1 implements Serializable,EntryPoint
{
public void onModuleLoad() {
MyPopup p = new MyPopup();
RootPanel.get().add(p);
}
From my xhtml view i call this method:
<h:commandLink value="showPopup" action="#{scheduleHandler1.onModuleLoad}" />
Thanks for Help.
GWT is client side technology - the java code that you write compiles down to js+html and is executed inside the browser.
OTOH, SEAM is server side technology - code that you write executes on server when a request is made and the HTML is produced which is returned back to browser for display.
In this sense GWT and Seam do not go well together. Most certainly you can not mix the code in the same compile unit.
You could use Seam for server side REST and GWT on the client side to consume REST, but this would only make sense if you already had an existing Seam REST code.
If you have written some GWT code and want to include it in you html pages (static or produced by Seam) then use them as GWT host pages - you simply include script tag to include GWT js code in the page: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html
GWT and Seam can actually work together, as you can see in this page in the Seam Reference Documentation.
However, what it looks like you are trying to do, and where the problem looks to me, is that you are trying to mix JSF and GWT. You are trying to call a Seam action from JSF where that action calls some GWT code. Hence, your server side Seam code is calling the client side GWT code and you are getting the exception that says GWT.create() is only usable in client code! It cannot be called, for example, from server code. I'm not sure why you're trying to do this.
JSF is a client side technology, written in XHTML. GWT is also a client side technology written in, well, Java. I'm not sure how these play together.
On the other hand, there is no reason, as per the link above, why your GWT widgets cannot call your Seam components. You just need to follow the instructions.