Returning JSON in GWT - java

I'm still pretty new to JSON and GWT and I'm trying to figure out how to pass JSON data back from a page into my GWT app. I pass the JSON back to a class:
public class GetProductTree extends JavaScriptObject {
protected GetProductTree() { }
public final native String getCustomerName() /*-{ return this.customername; }-*/;
}
It's pretty basic and not complete at this moment so I'm just trying (for now) to make sure I can get something back.
The code to call this is:
submitProject.addClickListener(new ClickListener() {
public void onClick(Widget w) {
RequestBuilder.Method method=RequestBuilder.GET;
final String url1 = "http://localhost:8500/getProducts.cfm";
//Window.alert(url1);
RequestBuilder rb = new RequestBuilder(method, url1);
try {
rb.sendRequest(null, new RequestCallback() {
public void onResponseReceived(Request request, Response response) {
JSONObject oResults = (JSONObject) JSONParser.parse(response.getText());
GetProductTree oResponse = oResults.isObject().getJavaScriptObject().cast();
Window.alert(oResponse.getCustomerName());
}
public void onError(Request arg0, Throwable arg1) {
Window.alert("error");
}
});
} catch (RequestException e) {
}
}
});
However I get an error:
No source code is available for type
XYZ.GetProductTree; did
you forget to inherit a required
module?
I am importing the correct package for XYZ.GetProductTree on the call page. What am I missing?

This error is from the compiler, complaining that it can't find that type in it's classpath. For the GWT compiler to find your classes they have to be and in your classpath, and they have to be referenced in a .gwt.xml module file as well. Can you post your package names and the contents of your .gwt.xml files? My guess is that wherever you have put this class it's not visible to the GWT compiler.

I am so obtuse sometimes. I forgot about having to add the source path for my new package. I added this to a "data" package which I just created and didn't add the path to the XML. Thanks :)

Related

Serenity screenplay pattern- upload file

We are trying cucumber serenity framework for end to end tests. I am fairly new the technology and I tired this simple code below.
actor.attemptsTo(Enter.theValue(path).into(Upload));
where path is the location of file i am trying to upload using browser's upload widget.Has anyone ever managed to perform actions like this using serenity screen play pattern.
Its really making us think of giving up serenity and just use cucumber-selenium framework as I can easily perform this using Upload.sendkeys(path);
Any help is much appreciated. Thanks in advance.
AS requested: Listing Steps:
public class ListingSteps
{
#Before
public void set_the_stage() {
OnStage.setTheStage(new OnlineCast());
}
#Given("^(.*) is able to click import products$") public void userIsAbleToClick(String actorName) throws Throwable
{
theActorCalled(actorName).wasAbleTo(Start.theApplication());
}
#When("^s?he imports a single item successfully$") public void heImportsASingleItemSuccessfully() throws Throwable
{
theActorInTheSpotlight().attemptsTo(Import.spreadsheet());
}
#Then("^(.*) are listed on ebay and amazon with all the right information$") public void itemsAreListedOnEbayAndAmazonWithAllTheRightInformation(String actorName, String SKU)
throws Throwable
{
//pending
}
Ignore then for now as its work in progress.
Import class:
public class Import implements Task
{
protected String path =
"C:\\somePathToFile\\populated_excel.xlsx";
public static Import spreadsheet()
{
return instrumented(Import.class);
}
#Override public <T extends Actor> void performAs(T actorName)
{
actorName.attemptsTo(Click.on(Products.ProductsScreen));
actorName.attemptsTo(Click.on(Products.Upload));
actorName.attemptsTo(Enter.theValue(path).into(Browse).thenHit(Keys.RETURN));//this is the line which is giving errors
actorName.attemptsTo(Click.on(Products.UploadButton));
}
}
Target Browse
public class Products
{
public static Target Browse = Target.the("browse file").locatedBy("//input[#type='file']");
}
Did you try removing these lines?
actorName.attemptsTo(Click.on(Products.ProductsScreen));
actorName.attemptsTo(Click.on(Products.Upload));
You don't need to open the upload file component, only write the file path directly to the input file element and perform the submit.
The way I managed to get this working was by using the FileToUpload class:
import net.thucydides.core.pages.components.FileToUpload;
FileToUpload fileToUpload = new FileToUpload(driver, fileName);
fileToUpload.fromLocalMachine().to(webElement);
I got this working with a simple:
import java.nio.file.*;
Path data = null;
try {
data = Paths.get(ClassLoader.getSystemResource(file).toURI());
} catch (URISyntaxException ignore) {}
ACTOR.attemptsTo(Upload.theFile(data).to(target));
file is an actual file that exists on your classpath, in src/test/resources if you have a Maven project.
target is something like:
Target.the("Image upload").located(By.xpath("//input[#type='file']"));

How to call Java method (custom class) with an interface typed parameter in Nativescript

I'm creating a Nativescript plugin. It includes a custom Android Library (AAR) and I want to use it from the Typescript code. When I run a demo (in device or emulator) I get a TypeError: sender.registerListener is not a function error when calling this registerListener method, which is weird because I'm able to call other methods of the same object.
I think that it could be because I am not implementing properly the interface required as parameter. I think that I can explain it better with code:
Sender.java: the public class I will use in Typescript:
package com.berriart.android.myplugin;
public class Sender {
public static final String TAG = "Sender";
private Context _context = null;
public Sender(Context context) {
_context = context;
}
public void send(final String messagePath, final String messageToSend) {
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "Send call: " + messagePath + " " + messageToSend);
}
}
public void registerListener(MessageListener listener) {
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "registerListener");
}
}
// Other code here
}
MessageListener.java: the interface that must be implemented by the registerListener parameter:
package com.berriart.android.myplugin;
public interface MessageListener {
void receive(String messagePath, String messageReceived);
}
This is the Typescript (Nativescript) code of the plugin ( to ):
import * as app from "tns-core-modules/application";
export class WearMessaging {
public static send(messagePath: string, messageToSend: string) {
let sender = new com.berriart.android.myplugin.Sender(app.android.context);
sender.send(messagePath, messageToSend);
}
public static registerListener(receiveCallback: (messagePath: string, messageReceived: string) => void) {
let messageListener = new com.berriart.android.myplugin.MessageListener({
receive: receiveCallback
});
let sender = new com.berriart.android.myplugin.Sender(app.android.context);
sender.registerListener(messageListener);
}
}
If I include WearMessaging.send("/demo", "Hola"); in my nativescript application it compiles and run properly, it's call the Java method successfuly. But if I run:
WearMessaging.registerListener((messagePath: string, messageReceived: string) => {
console.log(messagePath);
console.log(messageReceived);
});
The application stops at run time and throws: TypeError: sender.registerListener is not a function refering to the myplugin.android.ts file.
I'm getting crazy trying to make this work, so, let me know if you have any clue. As I say I think that is because I'm missing something when implementing the interface and because the parameter type do not match them method is not being recognized, but maybe I'm wrong.
Here you can see some official doc:
https://docs.nativescript.org/runtimes/android/generator/extend-class-interface
Thanks in advance.
Ok, I solved it :S
It seems that the incremental build was doing something wrong. After deleting manually the build files of the demo everything went fine:
rm -rf platforms/android/build/*
rm -rf platforms/android/app/build/*
# Then build & deploy again
So, question code seems to be fine if you need to do something similar.

How to pass the JSON object in java function using JSNI?

I am learning GWT, I am trying following example in which I have tried to pass the JSON object in java function.
public class HomeController implements EntryPoint {
public void onModuleLoad() {
createTestNativeFunction();
Presenter presenter = new PersenterImpl();
presenter.go(RootPanel.get());
}
public native void createTestNativeFunction()/*-{
parser: function() {
var that = this;
var jsonResult = JSON.parse({id:42,name:'yo'});
return this.#com.easylearntutorial.gwt.client.HomeController::onParse(Lorg/sgx/jsutil/client/JsObject;)(jsonResult);
}
void onParse(jsonResult){
System.out.println(jsonResult);
}
}
}-*/;
}
I am getting following errors:
Tracing compile failure path for type 'com.easylearntutorial.gwt.client.HomeController'
[ERROR] Errors in 'file:/C:/Users/ameen/workspace/Tutorial/src/com/easylearntutorial/gwt/client/HomeController.java'
[ERROR] Line 31: missing ; before statement
void onParse(jsonResult){
--------------------------------^
[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
[WARN] Server class 'com.google.gwt.dev.shell.jetty.JDBCUnloader' could not be found in the web app, but was found on the system classpath
[WARN] Adding classpath entry 'file:/C:/Program%20Files/gwt-2.7.0/gwt-dev.jar' to the web app classpath for this session
For additional info see: file:/C:/Program%20Files/gwt-2.7.0/doc/helpInfo/webAppClassPath.html
You really should try to avoid JSNI. You can probably write 99% of your code not using JSNI at all. If you really need it, you should use the new JsInterop instead, documentation still in early stage but you can see this documentation here.
If you need to use JsInterop or JSNI it is usually because you need to wrap a JS lib, so first, try to find if it is already wrapped. If it is not you can always use some other wrapper library to learn how to wrap your JS lib.
OpenLayers JsInterop wrapper https://github.com/TDesjardins/gwt-ol3
OpenLayers JSNI wrapper (deprecated) https://github.com/geosdi/GWT-OpenLayers
Or explore github https://github.com/search?q=topic%3Agwt+topic%3Ajsinterop
System.out.println() is a java function, you are looking for console.log().
The body of the native is JavaScript, not Java.
You are declare you variable jsonResult into your parser: function(), jsonResult only exist into that function. Thats why the system say you that
missing ; before statement
Because you never declare the varieble into createTestNativeFunction().
Plus sjakubowski is right System.out.println() is a java function, you need to use console.log() on JavaScript.
Try this:
public native void createTestNativeFunction(){
var jsonResult = {};
parser: function() {
var that = this;
jsonResult = JSON.parse({id:42,name:'yo'});
return this.#com.easylearntutorial.gwt.client.HomeController::onParse(Lorg/sgx/jsutil/client/JsObject;)(jsonResult);
}
void onParse(jsonResult){
console.log(jsonResult);
}
}
I did the following to solve my errors.
public class HomeController implements EntryPoint {
public void onModuleLoad() {
createTestNativeFunction();
Presenter presenter = new PersenterImpl();
presenter.go(RootPanel.get());
}
// var jsonResult = JSON.parse({id:42,name:'yo'});
public native void createTestNativeFunction()/*-{
var that = this;
$wnd.testFunction = function(jsonResult) {
that.#com.easylearntutorial.gwt.client.HomeController::onParse(Lorg/sgx/jsutil/client/JsObject;)(jsonResult);
};
}-*/;
public void onParse(JsObject jsonResult){
int i =42;
}
}

Migration to wicket 1.5 - resource (path) issue

I got the task to migrate to wicket 1.4 to wicket 1.5. Despite lack of information in migration guide I was somehow able to refactor most issues. Unfortunetly I'm stuck with "resource" - atm I'm getting this error
java.lang.IllegalArgumentException: Argument 'resource' may not be null.
What I understand by that is that something was change and wicket can no longer "get" to my resources. So I used to have (in wicket 1.4) that piece of code that was responsible for creating image and passing it (the method is in class that extends WebPage) :
private void addImageLogo() {
Resource res = new Resource() {
#Override
public IResourceStream getResourceStream() {
String logo = ConfigurationManager.getInstance().getPathValue(ConfigurationManager.LOGO_FILE_PATH);
return new FileResourceStream(new File(logo));
};
Image logo = new Image("logo", res);
add(logo);
}
Now Resource class no longer exists or I can't find it. While searching internet I was able to change it into this
private void addImageLogo() {
String logoTxt = ConfigurationManager.getInstance().getPathValue(ConfigurationManager.LOGO_FILE_PATH);
ResourceReference res = new ResourceReference(logoTxt) {
#Override
public IResource getResource() {
return null;
}
};
Image logo = new Image("logo", res);
add(logo);
}
This is responsible for obtaining path (and its working): ConfigurationManager.getInstance().getPathValue(ConfigurationManager.LOGO_FILE_PATH)
Unfortunetly I'm still getting this error that I mentioned above. The method getResource() generated automaticly and I believe this is an issue because I'm retuning null but I have no idea what (or how) should I return.
Since it worked with a IResourceStream in 1.4.x then you can just use org.apache.wicket.request.resource.ResourceStreamResource as a IResource for the Image.
Your first code snippet is not complete so I cannot give you exact replacement code.

Java structure/pattern(s) to return specific field from subclasses

For a project we have a requirement to create an interfacedefinition that will return all available filetype extensions that our component can export...
The problem is that we want avoid configuration/properties files. We don't want to edit our configuration/propertie file when another filetype is added (in the future). The structure of this part of our component is as follows:
public abstract class FileType {
protected String filetype;
public FileType(String filetype){
this.filetype = filetype;
}
public abstract void export(String path, Object information);
}
public class PdfExport extends FileType {
public PdfExport() {
super("pdf");
}
public void export(String path, Object information){
//pdf specific logic
}
}
But how do we solve this when another component calls the interfacedefinition getExportTypes()? (How do we get a list of all available filetypes?) Taking into account the requirement to add in the future new classes that extend abstract class filetype (add new filetypes)?
Does anyone has suggestions, maybe another structure of above example? Or any (design) that discuss above issue?
Thanks in advance!
You could do something like this:
public interface FileType {
public String getFileType();
public void export(String path, Object info);
}
public enum DefaultFileType implements FileType {
PDF(".pdf"){
public void export(String path, Object info) {
// do pdf stuff
}
}, TXT(".txt"){
public void export(String path, Object info) {
//do txt stuff
}
};
private final String fileType;
private DefaultFileType(String fileType) {
this.fileType = fileType;
}
public String getFileType() {
return fileType;
}
public abstract void export(String path, Object info);
}
Then you can have a Set<FileType> in your class of all the supported FileTypes. This way anyone who wants to add a supported FileType but cannot edit your enum can still do so.
This is the exact purpose of the strategy pattern. The strategies here are the FileTypes that encapsulate an algorithm that exports a file.
In the following example:
public class Application{
List<FileType> exporters = new ArrayList<FileType>();
public void addExporter(FileType fileExporter){
exporters.add(fileExporter);
}
public void exportData(Object information){
for(FileType exporter : exporters){
exporter.export("d:\Export", information);
}
}
}
The Application class holds a list of exporters that can be filled out on the go. The Application class does not have to know what type of file exporter is registered nor how the file can be exported. When the data is exported, the Applicaiton class loops through registered exporters and delegates the export task to each one of them.
EDIT Below is an example of the Application class usage.
// Define a pdf exporter
PdfExport pdfExport = new pdfExport();
Application app = new Application();
// Register the new exporter
app.addExporter(pdfExport);
// Export some data...
app.export(information);
EDIT How to avoid configuration files and changing the code everytime you have a new FileType?
You can load the exporters at runtime using reflexion (see this link for details)
You can use reflection to scan classes which implement your interface.
Have a look at similar question: At runtime, find all classes in a Java application that extend a base class

Categories