I use the GWT RequestBuilder, and for testing purposes, I'd like to load a json file in the server.
It works perfectly with the DevMode, but throw a 404 error with GWTTestCase.
With RPC, there is a fix adding <servlet path=".." class="..."/>, but what can I do with static content ?
I could easily use #TextResource, but it's not the goal of my UnitTest (which is in fact a functionnal test)
Static resources can be bundled with a module by putting them in the module's public path.
I used (once again) Thomas's answer to resolve the problem. My module is io.robusta.fora.comments.Comment.gwt.xml and I've put my user.json file in the io.robsuta.fora.comments.resources package.
I had so to add in Comment.gwt.xml file : <public path="resources"/>
Then the GWTTestCase is straightforward :
public class GwtRestClientTest extends GWTTestCase{
#Override
public String getModuleName() {
return "io.robusta.fora.comments.Comments";
}
public void testGET(){
String base = GWT.getModuleBaseURL();
System.out.println(base); //-> http://192.168.0.10:53551/io.robusta.fora.comments.Comments.JUnit/
GwtRestClient client = new GwtRestClient(base); //base url
AsyncCallback<String> cb = new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
System.out.println(result);//->{id:1,email:"jo#robusta.io"}
finishTest();
}
#Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
};
client.GET("user.json", null, cb);//fetch my json file with no params
delayTestFinish(3000);
}
}
Related
I have an existing app that I'm adding a "Suggested Products" feature to and I'm having trouble with my JSONP response not being properly transformed to the typed JsArray. I'm hoping someone can give me an idea of what I'm doing wrong?
I have defined my type that will be returned from the server in its own class:
import com.google.gwt.core.client.JavaScriptObject;
public class SuggestedProduct extends JavaScriptObject {
protected SuggestedProduct() {}
public final native String getFormName();
public final native String getImageURL();
}
I have a method that uses the JsonpRequestBuilder to fire off a request to get my JSON.
private void loadSuggestedProducts() {
JsonpRequestBuilder builder = new JsonpRequestBuilder();
builder.requestObject(buildSuggestedProductURL(), new AsyncCallback<JsArray<SuggestedProduct>>() {
public void onFailure(Throwable caught) {
//Handle errors
}
public void onSuccess(JsArray<SuggestedProduct> data) {
if ( data == null) {
//Handle empty data
return;
}
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendHtmlConstant("<h4>Suggested Products:</h4>");
for (int i=0; i < data.length(); i++) {
SuggestedProduct product = data.get(i); //<- This line throws the exception
sb.appendHtmlConstant("<div class=\"card\">");
sb.appendHtmlConstant("<img class=\"card-img-top\" src=\"" + product.getImageURL() + "\" alt=\"" + product.getFormName() + "\">");
sb.appendHtmlConstant("<div class=\"card-body\">");
sb.appendHtmlConstant("<h5 class=\"card-title\">" + product.getFormName() + "</h5>");
sb.appendHtmlConstant("<a onclick=\"javascript:addItems();\" class=\"cmd-add\">Add <i aria-hidden=\"true\" class=\"fa fa-plus-circle\"></i></a>");
sb.appendHtmlConstant("</div></div>");
}
view.getSuggestedProducts().setInnerSafeHtml(sb.toSafeHtml());
}
});
}
When I try to use a SuggestedProduct from the response, I get an error:
java.lang.IncompatibleClassChangeError: Found interface
com.google.gwt.cor.client.JsArray, but class was expected
I've been following the guide in the GWT documentation. I don't see any difference between what I'm trying and what they say will work. When I debug, it looks as though the returned data is an array of SuggestedProducts, so I'm stumped as to how to proceed. Any help would be appreciated.
After closer inspection I realized my overlay type was missing method bodies for what fields to return from the JSON object they represented. The fix was to include the proper JSNI method definitions.
import com.google.gwt.core.client.JavaScriptObject;
public class SuggestedProduct extends JavaScriptObject {
protected SuggestedProduct() {}
public final native String getFormName() /*-{ return this.formname; }-*/;
public final native String getImageURL() /*-{ return this.imageurl; }-*/;
}
I'm trying to add a custom HeaderResponseContainer in my wicket application. The tutorial looks quite simple (see Positioning of contributions), but when I add these lines and run the application I alwas get an IllegalStateException:
java.lang.IllegalStateException: No FilteringHeaderResponse is present in the request cycle. This may mean that you have not decorated the header response with a FilteringHeaderResponse. Simply calling the FilteringHeaderResponse constructor sets itself on the request cycle
at org.apache.wicket.markup.head.filter.FilteringHeaderResponse.get(FilteringHeaderResponse.java:165)
at org.apache.wicket.markup.head.filter.HeaderResponseContainer.onComponentTagBody(HeaderResponseContainer.java:64)
at org.apache.wicket.markup.html.panel.DefaultMarkupSourcingStrategy.onComponentTagBody(DefaultMarkupSourcingStrategy.java:71)
...
Yes, I already saw the note about FilteringHeaderResponse. But I am not sure where I should call the constructor. I already tried to add it in renderHead before calling response.render but I still get the same exception:
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
FilteringHeaderResponse resp = new FilteringHeaderResponse(response);
resp.render(new FilteredHeaderItem(..., "myKey"));
}
You can create a decorator that wraps responses in a FilteringHeaderResponse:
public final class FilteringHeaderResponseDecorator implements IHeaderResponseDecorator {
#Override
public IHeaderResponse decorate(IHeaderResponse response) {
return new FilteringHeaderResponse(response);
}
}
And that set it during application initialization:
Override
public void init() {
super.init();
setHeaderResponseDecorator(new FilteringHeaderResponseDecorator());
}
I just ran into this same problem and found that the Wicket In Action tutorial leaves out the part about setting up a custom IHeaderResponseDecorator in your main Wicket Application init. The Wicket guide has a more thorough example:
Apache Wicket User Guide - Put JavaScript inside page body
You need something like this in your wicket Application:
#Override
public void init()
{
setHeaderResponseDecorator(new JavaScriptToBucketResponseDecorator("myKey"));
}
/**
* Decorates an original IHeaderResponse and renders all javascript items
* (JavaScriptHeaderItem), to a specific container in the page.
*/
static class JavaScriptToBucketResponseDecorator implements IHeaderResponseDecorator
{
private String bucketName;
public JavaScriptToBucketResponseDecorator(String bucketName) {
this.bucketName = bucketName;
}
#Override
public IHeaderResponse decorate(IHeaderResponse response) {
return new JavaScriptFilteredIntoFooterHeaderResponse(response, bucketName);
}
}
I have a new Play 2 project with play-authenticate. I wrote some simple test cases for the REST API. Tests pass fine on the console but I cannot make some of them pass in Eclipse.
#Test
public void testWithoutAuth() {
running(testServer(3333), new Runnable() {
#Override
public void run() {
Response response = WS.url("http://localhost:3333/secretarea").get().get();
assertThat(response.getStatus()).isEqualTo(FORBIDDEN);
}
});
}
This example passes fine on the console but in Eclipse fails with response error code 500. it looks like the application setup is not ok (e.g. my own AuthProvider not found). Has anyone managed to get such tests working in Eclipse?
Finally sorted this out. The trick is to create FakeApplicatio with custom config. In my case the setup is like this:
#Test
public void testWithoutAuth() {
List<String> plugins = new ArrayList<String>();
plugins.add("be.objectify.deadbolt.DeadboltPlugin");
plugins.add("service.MyUserServicePlugin");
plugins.add("providers.MyUsernamePasswordAuthProvider");
FakeApplication fa = fakeApplication(new HashMap<String,String>(), plugins);
running(testServer(3333, fa), new Runnable() {
#Override
public void run() {
Response response = WS.url("http://localhost:3333/secretarea").get().get();
assertThat(response.getStatus()).isEqualTo(FORBIDDEN);
}
});
}
I am new to GWT and am trying to implement a file upload functionality.
Found some implementation help over the internet and used that as reference.
But have some questions related to that:
The actual upload or writing the contents of file on server(or disk) will be done by a servlet.
Is it necessary that this servlet (say MyFileUploadServlet) extends HttpServlet? OR
I can use RemoteServiceServlet or implement any other interface? If yes, which method do I need to implement/override?
In my servlet, after everything is done, I need to return back the response back to the client.
I think form.addSubmitCompleteHandler() can be used to achieve that. From servlet, I could return text/html (or String type object) and then use SubmitCompleteEvent.getResults() to get the result.
Question is that can I use my custom object instead of String (lets say MyFileUploadResult), populate the results in it and then pass it back to client?
or can I get back JSON object?
Currently, after getting back the response and using SubmitCompleteEvent.getResults(), I am getting some HTML tags added to the actual response such as :
pre> Image upload successfully /pre> .
Is there a way to get rid of that?
Thanks a lot in advance!
Regards,
Ashish
To upload files, I have extended HttpServlet in the past. I used it together with Commons-FileUpload.
I made a general widget for form-based uploads. That was to accommodate uploads for different file types (plain text and Base64). If you just need to upload plain text files, you could combine the following two classes into one.
public class UploadFile extends Composite {
#UiField FormPanel uploadForm;
#UiField FileUpload fileUpload;
#UiField Button uploadButton;
interface Binder extends UiBinder<Widget, UploadFile> {}
public UploadFile() {
initWidget(GWT.<Binder> create(Binder.class).createAndBindUi(this));
fileUpload.setName("fileUpload");
uploadForm.setEncoding(FormPanel.ENCODING_MULTIPART);
uploadForm.setMethod(FormPanel.METHOD_POST);
uploadForm.addSubmitHandler(new SubmitHandler() {
#Override
public void onSubmit(SubmitEvent event) {
if ("".equals(fileUpload.getFilename())) {
Window.alert("No file selected");
event.cancel();
}
}
});
uploadButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
uploadForm.submit();
}
});
}
public HandlerRegistration addCompletedCallback(
final AsyncCallback<String> callback) {
return uploadForm.addSubmitCompleteHandler(new SubmitCompleteHandler() {
#Override
public void onSubmitComplete(SubmitCompleteEvent event) {
callback.onSuccess(event.getResults());
}
});
}
}
The UiBinder part is pretty straighforward.
<g:HTMLPanel>
<g:HorizontalPanel>
<g:FormPanel ui:field="uploadForm">
<g:FileUpload ui:field="fileUpload"></g:FileUpload>
</g:FormPanel>
<g:Button ui:field="uploadButton">Upload File</g:Button>
</g:HorizontalPanel>
</g:HTMLPanel>
Now you can extend this class for plain text files. Just make sure your web.xml serves the HttpServlet at /textupload.
public class UploadFileAsText extends UploadFile {
public UploadFileAsText() {
uploadForm.setAction(GWT.getModuleBaseURL() + "textupload");
}
}
The servlet for plain text files goes on the server side. It returns the contents of the uploaded file to the client. Make sure to install the jar for FileUpload from Apache Commons somewhere on your classpath.
public class TextFileUploadServiceImpl extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
if (! ServletFileUpload.isMultipartContent(request)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
"Not a multipart request");
return;
}
ServletFileUpload upload = new ServletFileUpload(); // from Commons
try {
FileItemIterator iter = upload.getItemIterator(request);
if (iter.hasNext()) {
FileItemStream fileItem = iter.next();
// String name = fileItem.getFieldName(); // file name, if you need it
ServletOutputStream out = response.getOutputStream();
response.setBufferSize(32768);
int bufSize = response.getBufferSize();
byte[] buffer = new byte[bufSize];
InputStream in = fileItem.openStream();
BufferedInputStream bis = new BufferedInputStream(in, bufSize);
long length = 0;
int bytes;
while ((bytes = bis.read(buffer, 0, bufSize)) >= 0) {
out.write(buffer, 0, bytes);
length += bytes;
}
response.setContentType("text/html");
response.setContentLength(
(length > 0 && length <= Integer.MAX_VALUE) ? (int) length : 0);
bis.close();
in.close();
out.flush();
out.close();
}
} catch(Exception caught) {
throw new RuntimeException(caught);
}
}
}
I cannot recall how I got around the <pre></pre> tag problem. You may have to filter the tags on the client. The topic is also addressed here.
I am running a basic GWT application in IntelliJ, below is my code
public class test implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
final Button button = new Button("Click me");
final Label label = new Label();
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
if (label.getText().equals("")) {
testService.App.getInstance().getMessage("h", new AsyncCallback<Inter>() {
public void onFailure(Throwable caught) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void onSuccess(Inter result) {
label.setText(result.getToken());
}
});
} else {
label.setText("");
}
}
});
Impl Class
public class testServiceImpl extends RemoteServiceServlet implements testService {
// Implementation of sample interface method
public Inter getMessage(String msg) {
RdbHelper rdbHelper = new RdbHelper();
return rdbHelper.getMsg();
}
}
RdbHelper Class
public class RdbHelper {
public Inter getMsg(){
Inter inter = new Inter();
return inter;
}
}
Inter Class
public class Inter implements Serializable{
private String token ;
public String getToken() {
token = "Hello";
return token;
}
public void setToken(String token) {
this.token = token;
}
}
I should see msg "Hello" but i am getting this error .
ERROR: Errors in 'file:/C:/work/Grails/TestFinal/src/com/test/client/test.java'.
ERROR: Unable to find type 'com.test.client.test'.
ERROR: Line 28: No source code is available for type com.test.shared.Inter; did you forget to inherit a required module?.
ERROR: Hint: Previous compiler errors may have made this type unavailable.
ERROR: Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly.
ERROR: Failed to load module 'test' from user agent 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7' at 127.0.0.1:51070.
Note: I am trying the same thing in Eclipse and its working fine, but this is the Issue i am facing in IntelliJ
Did you remember to put
<source path="shared"/>
in your Module.gwt.xml file.
You need to do this to compile the code in shared package to javascript code. If not it only compiles the code in the client package and thereby the code in the shared folder is not available on client side.