GWT RPC call in onModuleLoad Implementation Failure - gwt

I am having an issue getting an initial RPC call to load data when the module is loaded.
I am adapting code from here and here.
The error that if fails on is a null pointer, and it behaves as if it is not even making the RPC call at all, since neither debug messages inside of the RPC appear in the test console in Eclipse.
The MenuItems object is an ArrayList < ArrayList < String > > object that implements IsSerializable and has a SerializableWhiteList entry as per this SO answer. This object is generated in an RPC RemoteServiceServlet.
The console also references the line
History.fireCurrentHistoryState();
in AppController.java (almost identical to the GWT Contacts example)
Ideas on why/where/how this is going astray? Any other implementation examples of initial RPC calls would be great also.
public class MVPtest implements EntryPoint {
MenuItems mItems;
public void onModuleLoad() {
MainServiceAsync rpcService = GWT.create(MainService.class);
System.out.println("Inside of mod load. rpcService = " + rpcService.toString());
rpcService.getMenuItems(new AsyncCallback<MenuItems>() {
public void onFailure(Throwable caught) {
System.out.println("I failed...");
caught.printStackTrace();
}
public void onSuccess(MenuItems result) {
System.out.println("I got the menuitems.");
mItems = result;
}
});
HandlerManager eventBus = new HandlerManager(null);
AppController appViewer = new AppController(rpcService, eventBus, mItems);
appViewer.go(RootLayoutPanel.get());
}
}
The rpcService debug message yields a non-null:
Inside of mod load. rpcService = com.******.******.test.client.MainService_Proxy#4f07f3b5

This statement is dangerous:
AppController appViewer = new AppController(rpcService, eventBus, mItems);
because your code on the client side will be executed without witing for the response of your call.
Something like this should work:
public class MVPtest implements EntryPoint {
MenuItems mItems;
public void onModuleLoad() {
MainServiceAsync rpcService = GWT.create(MainService.class);
System.out.println("Inside of mod load. rpcService = " + rpcService.toString());
rpcService.getMenuItems(new AsyncCallback<MenuItems>() {
public void onFailure(Throwable caught) {
System.out.println("I failed...");
caught.printStackTrace();
}
public void onSuccess(MenuItems result) {
System.out.println("I got the menuitems.");
mItems = result;
HandlerManager eventBus = new HandlerManager(null);
AppController appViewer = new AppController(rpcService, eventBus, mItems);
appViewer.go(RootLayoutPanel.get());
}
});
}
}

Related

UiEditor/RequestFactory generate null delegate on ValueProxy

I have a Service.class ValueProxy in a service oriented architecture (i have a server method like "storeService(service)".
I would use an Editor with RequestFactoryEditorDriver.
I expect all work, but when i call driver.edit(service) i get a null delegate exception.
Why? It's a bug?
At http://crazygui.wordpress.com/tag/editor/ i find a sample of implementation...only differece with mine is SimpleBeanRequestEditorDriver.class (i have RequestFactoryEditorDriver.class)
ServiceEditor.class
public class ServiceEditor extends Composite implements Editor<ServiceProxy>{
private static final Logger logger = Logger.getLogger(ServiceEditor.class.getName());
private static ServiceEditorUiBinder uiBinder = GWT
.create(ServiceEditorUiBinder.class);
interface ServiceEditorUiBinder extends
UiBinder<Widget, ServiceEditor> {
}
//~Driver ==========================================================================================================================
interface Driver extends RequestFactoryEditorDriver<ServiceProxy, ServiceEditor> {
}
Driver driver;
//====================================================================================================================================
#UiField
Decorator<String> name;
#UiField
Decorator<String> description;
#UiField
Decorator<String> notes;
#UiField
Decorator<String> citiesString;
// #UiField(provided=true)
// Decorator<String> category;
// MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
// #UiField(provided=true)
// #Ignore
// SuggestBox suggestBox = new SuggestBox(oracle);
private BigInteger organizationId;
private EditorDelegate<ServiceProxy> delegate;
public ServiceEditor() {
initWidget(uiBinder.createAndBindUi(this));
driver = GWT.create(Driver.class);
}
#Override
protected void onLoad() {
driver.initialize(ClientFactory.AppInjector.getRequestFactory(),this);
}
public void edit() {
ServiceRequestContext requestContext = ClientFactory.AppInjector.getRequestFactory().getNewServiceContext();
edit(requestContext.create(ServiceProxy.class),requestContext);
}
public void display(ServiceProxy p){
driver.display(p);
}
public void edit(ServiceProxy p) {
ServiceRequestContext requestContext = ClientFactory.AppInjector.getRequestFactory().getNewServiceContext();
edit(p,requestContext);
}
public void edit(ServiceProxy service,ServiceRequestContext requestContext) {
if(service.getToken()==null) {
requestContext.addServiceToOrganization(organizationId, service);
//TODO: attenzione a tempistiche chiamate;
SessionRPC.Util.getInstance().getOrganizationId(new AsyncCallback<BigInteger>() {
#Override
public void onSuccess(BigInteger result) {
organizationId = result;
}
#Override
public void onFailure(Throwable caught) {
}
});
}
else
requestContext.updateService(service);
driver.edit(service,requestContext);
}
public RequestContext flush2(){
return driver.flush();
}
public void submit(Receiver<Void> receiver){
RequestContext context = driver.flush();
if (driver.hasErrors()) {
Window.alert("Driver errors!");
return;
}
context.fire(receiver);
}
public void notifyErrors(Set<ConstraintViolation<?>> violations) {
driver.setConstraintViolations(violations);
//driver.getErrors().get(0).
logger.info("Validation Errors: /n "+driver.getErrors().toString());
}
// #Override
// public void setDelegate(EditorDelegate<ServiceProxy> delegate) {
// this.delegate = delegate;
// }
}
ActivitySnippet...
ServiceEditor serviceEditor = GWT.create(ServiceEditor.class);
serviceEditor.display(response);
Stack trace...
Caused by: com.google.gwt.core.client.JavaScriptException: (TypeError) : Cannot set property 'request' of undefined
at Unknown.$collect(JsArrayString.java:42)
at Unknown.fillInStackTrace_2(StackTraceCreator.java:180)
at Unknown.fillInStackTrace_0(StackTraceCreator.java:518)
at Unknown.fillInStackTrace(Throwable.java:115)
at Unknown.Throwable_0(Throwable.java:51)
at Unknown.Exception_0(Exception.java:25)
at Unknown.RuntimeException_0(RuntimeException.java:25)
at Unknown.JavaScriptException_1(JavaScriptException.java:117)
at Unknown.JavaScriptException_0(JavaScriptException.java:109)
at Unknown.getCachableJavaScriptException(Exceptions.java:45)
at Unknown.wrap(Exceptions.java:29)
at Unknown.$setRequestContext(RequestFactoryEditorDelegate.java:80)
at Unknown.$edit(AbstractRequestFactoryEditorDriver.java:168)
at Unknown.display_0(AbstractRequestFactoryEditorDriver.java:159)
at Unknown.$show_2(ServiceEditor.java:91)
This means that getDelegate() method (line 168 of AbstractRequestFactoryEditorDriver.class) return null.
If you call RequestFactoryEditorDriver.show, it essentially just calls RequestFactoryEditorDriver.edit, but without a requestcontext. This otherwise should follow the same basic path in terms of how the driver needs to be wired up.
In this case, if the delegate is null, then the driver hasn't been initialized. From your code:
public ServiceEditor() {
initWidget(uiBinder.createAndBindUi(this));
driver = GWT.create(Driver.class);
}
#Override
protected void onLoad() {
driver.initialize(ClientFactory.AppInjector.getRequestFactory(),this);
}
public void edit() {
ServiceRequestContext requestContext = ClientFactory.AppInjector.getRequestFactory().getNewServiceContext();
edit(requestContext.create(ServiceProxy.class),requestContext);
}
public void display(ServiceProxy p){
driver.display(p);
}
You never listed the code that shows when edit or display are being called, so I'm mostly guessing here, but it looks like your other code looks roughly like this:
ServiceEditor editor = new ServiceEditor();//create ui, create driver.
editor.display(data);//driver.display, which calls driver.edit
parentWidget.add(editor);// causes onLoad to be called if actually
//attached to the dom, which causes driver.initialize
This is wrong. The driver must be initialized before you attempt to edit or display, since otherwise it doesn't know which editor objects it should be working with.
Instead, move driver.initialize to earlier than onLoad, like in the ServiceEditor constructor itself, or in some init method which allows you to call it earlier deliberately. Another option is to just call parent.add(editor) before editor.display(), though this may not work - make sure you understand what causes onLoad to be called.
(Please note that ServiceEditor.show is in your stack trace but not in your code listing, so I can't tell if the chance would be more obvious in seeing this.)

How can i return hash map from server to client

I have the following method on sever.
public HashMap<String,Set> select()
{
HashMap <String,Set> mp = new HashMap();
//some code
return mp;
}
whenver I am trying to return
<String , Set>
it is going onFailur
but I did this
<String , String >
then its success why this happning
i am using gwt RPC and my client code is
greetingService.select(usertextbox.getText(),new AsyncCallback<HashMap<String,Set>>()
{
public void onFailure(Throwable caught) {
Window.alert("not done");
}
#Override
public void onSuccess(HashMap hm) {
Window.alert("done");
}
Service code is
HashMap<String, Set> select(String user);
service implmentation is
public HashMap<String,Set> select(String user)
{
try {
Session studentDbSession = new Session("localhost",5984);
Database db = studentDbSession.getDatabase("hello");
Document d = db.getDocument("xyz");
JSONArray key = d.names().discard(0).discard(0);
for(int i=0;i<key.size();i++)
{
if(d.containsKey(key.get(i)))
{
k=key.getString(i);
Set aaa=d.getJSONObject(key.getString(i)).entrySet();
System.out.println("----------------");
mp.put(k,aaa);
return mp;
}
Always try to avoid Raw type. Let me share you a sample code. Try it at you end with this sample first or validate all the classes of your code.
Sample code:
RemoteService interface
#RemoteServiceRelativePath("greet")
public interface GreetingService extends RemoteService {
public HashMap<String, Set<String>> select(String input) throws IllegalArgumentException;
}
GreetingServiceAsync interface
public interface GreetingServiceAsync {
void select(String input, AsyncCallback<HashMap<String, Set<String>>> callback);
}
GreetingServiceImpl class
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
#Override
public HashMap<String, Set<String>> select(String input) throws IllegalArgumentException {
HashMap<String, Set<String>> output = new HashMap<String, Set<String>>();
Set<String> set = new HashSet<String>();
set.add("Hello " + input);
output.put("greeting", set);
return output;
}
}
Entry Point class
public void greetService() {
GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
greetingService.select("Mark", new AsyncCallback<HashMap<String, Set<String>>>() {
#Override
public void onSuccess(HashMap<String, Set<String>> result) {
Window.alert(result.get("greeting").iterator().next());
}
#Override
public void onFailure(Throwable caught) {
Window.alert("fail");
}
});
}
web.xml:
<servlet>
<servlet-name>gwtService</servlet-name>
<servlet-class>com.x.y.z.server.GWTServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gwtService</servlet-name>
<url-pattern>/moduleName/gwtService</url-pattern>
</servlet-mapping>
output:
What your GWT RPC call HashMap<String, Set> select(String user); does is following:
client-side: serialize String user in order to send it to server
server-side: deserialize RPC call, find implementation of select(String user) and execute it
server-side: serialize return value HashMap<String, Set> in order to return it to client
client-side: deserialize return value and call AsyncCallback
The problem lies in step 3), the serializing of HashMap<String, Set>. The HashMap itself is not the issue; it is the Set which causes the error. When serializing a raw class, GWT usually assumes that the generic type is <Object>. And since Object is not serializable in GWT, an exception is thrown.
Fix: As Braj already mentioned -- give your Set a serializible generic type, e. g. Set<String>, or define your own interface in a package which is accessable from both client- and server-side
public interface UserProperty extends IsSerializable{
}
and change the RPC method like this:
HashMap<String, Set<UserProperty> select(String user);
Have a look at Braj's answer for where to find all the places you need to change after changing your RPC method!

How to use same servlet for RPC and upload File in GWT.

i created a web application where i have to use fileUpload.
i have to send the file and their properties to server . For sending a file i used FormPanel and for properties i used RPC .
public void onModuleLoad() {
final FileServiceEndPoint serviceEndPoint = new FileServiceEndPoint();
new AddDocument();
Button b = new Button("addDocument");
b.addClickHandler(new ClickHandler() {
private Map<String, String> docProperty;
public void onClick(ClickEvent event) {
docProperty =getProperties();
AsyncCallback<String> callback = new AsyncCallback<String>() {
public void onSuccess(String result) {
System.out.println("he ha" +result);
}
public void onFailure(Throwable caught) {
}
};
serviceEndPoint.uploadAttachement(docProperty, callback);
}
});
RootPanel.get().add(b);
}
this new AddDocument(); contains code for uploading a file (formPanel code)
private FormPanel getFormPanel() {
if (uploadForm == null) {
uploadForm = new FormPanel();
uploadForm.setAction(GWT.getHostPageBaseURL() +"TestUploadFileServlet");
uploadForm.setEncoding(FormPanel.ENCODING_MULTIPART);
uploadForm.setMethod(FormPanel.METHOD_POST);
uploadForm.setWidget(getFileUpload());
System.out.println(GWT.getHostPageBaseURL() +"TestUploadFileServlet");
uploadForm.addFormHandler(new FormHandler() {
public void onSubmitComplete(FormSubmitCompleteEvent event) {
AddDocument.this.hide(true);
}
public void onSubmit(FormSubmitEvent event) {
}
});
}
return uploadForm;
}
private Button getAddButton() {
if (addButton == null) {
addButton = new Button("ADD");
addButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
uploadForm.submit();
}
});
addButton.setText("Add");
}
Interface is created for Sending property.
EndPoints:
public class FileServiceEndPoint implements FileServiceAsync{
FileServiceAsync service = (FileServiceAsync)GWT.create(FileService.class);
ServiceDefTarget endpoint = (ServiceDefTarget) service;
public FileServiceEndPoint() {
endpoint.setServiceEntryPoint(GWT.getHostPageBaseURL() + “TestUploadFileServlet”);
}
public void uploadAttachement(Map docProperty,
AsyncCallback callback) {
service.uploadAttachement(docProperty, callback);
}
}
On Server:
public class FileUploadImpl extends RemoteServiceServlet implements FileService {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(FileUploadImpl.class
.getName());
String a;
protected void service(final HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException {
a=”5″;
System.out.println(“ServletWorking Fine “);
}
public String uploadAttachement(Map docProperty) {
// TODO Auto-generated method stub
return “Checked”;
}
}
When I debug formPanel.submit : the debugger goes in Server and print ServletWorking Fine(this is perfect)
and when i debug the addProperties button it goes to server and print ServletWorking Fine. but It should not go in service method.
the debugger should go in UploadAttachement.
Plz tell how to pass hashMap using same servlet.

GWT RPC mechanism how to use non void return type

I have a scenario wherein I need to specify a return type to the Synchrnous function, the code is as follows :
#RemoteServiceRelativePath("show_box")
public interface ShowBoxCommandService extends RemoteService{
public ArrayList<String> showBox();
}
The implementation of the method on the server is :
public ArrayList<String> showBox() {
ArrayList<String> box = new ArrayList<String>();
Iterator<Box> boxes = BoxRegistry.getInstance().getBoxes();
while (boxes.hasNext()) {
box.add(boxes.next().toString());
}
return box;
}
I am trying to define the callback variable in the following format at the client side in order to call the method
AsyncCallback<Void> callback = new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
// TODO: Do something with errors.
// console was not started properly
}
#Override
public void onSuccess(Void result) {
// TODO Auto-generated method stub
// dialog saying that the console is started succesfully
}
};
update with the aync interface code :
public interface ShowBoxCommandServiceAsync {
void showBox(AsyncCallback<ArrayList<String>> callback);
}
But this is causing the definition of the method in the Async method to change.
Any ideas or clues will be helpful.
Thanks,
Bhavya
P.S. Apologies if this is a repetition
The callback should be:
AsyncCallback<ArrayList<String>> callback = new AsyncCallback<ArrayList<String>>() {
public void onFailure(Throwable caught) {
// TODO: Do something with errors.
// console was not started properly
}
#Override
public void onSuccess(ArrayList<String> result) {
// TODO Auto-generated method stub
// dialog saying that the console is started succesfully
}
};
If you don't need to utilize the result then you can ignore it, but if that is the case, you should probably question your design and why you would need the method to return an ArrayList<String> in the first place.
If the service interface looks like this:
public interface ShowBoxCommandService extends RemoteService {
public ArrayList<String> showBox();
}
then you must have an associated async interface:
public interface ShowBoxCommandServiceAsync {
public void showBox(AsyncCallback<ArrayList<String>> callback);
}
Which means, that the type of the callback that you should pass to showBox is AsyncCallback<ArrayList<String>>.
new AsyncCallback<ArrayList<String>>() {
#Override
public void onSuccess(ArrayList<String> list) {
// ...
}
#Override
public void onFailure(Throwable caught) {
// ...
}
}
Your callback should not be Void. If your synchronous method returns a List of Strings, the async callback method should receive the List. You'll have to use the ArrayList, because the class needs to implement the Serializable interface.
AsyncCallback<ArrayList<String>> callback = new AsyncCallback<ArrayList<String>>() {
public void onFailure(Throwable caught) {
// TODO: Do something with errors.
// console was not started properly
}
#Override
public void onSuccess(ArrayList<String> result) {
// TODO Auto-generated method stub
// dialog saying that the console is started succesfully
}
};
Huh? Your method returns an ArrayList and you are declaring void in your call?
Change <Void> to <ArrayList<String>>

GWT Void remote services fail for seemingly no reason

I'm working on a GWT project and have several void remote services that seem to execute just fine, but on the client side, end up firing the onFailure() method. No exceptions are thrown anywhere, and the expected behavior is observed on the backend. I have no idea what could be going wrong. Here is the relevant code:
Interfaces and implementation...
#RemoteServiceRelativePath("DeleteSearchService")
public interface DeleteSearchService extends RemoteService {
/**
* Utility class for simplifying access to the instance of async service.
*/
public static class Util {
private static DeleteSearchServiceAsync instance;
public static DeleteSearchServiceAsync getInstance(){
if (instance == null) {
instance = GWT.create(DeleteSearchService.class);
}
return instance;
}
}
public void delete(SearchBean search);
}
public interface DeleteSearchServiceAsync {
public void delete(SearchBean bean, AsyncCallback<Void> callback);
}
public class DeleteSearchServiceImpl extends RemoteServiceServlet implements DeleteSearchService {
private static final long serialVersionUID = 1L;
#Override
public void delete(SearchBean search) {
try {
Connection conn = SQLAccess.getConnection();
String sql = "DELETE FROM `searches` WHERE `id`=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, search.getSearchId());
ps.execute();
sql = "DELETE FROM `searchsourcemap` WHERE `search-id` = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, search.getSearchId());
ps.execute();
return;
} catch (Exception e) {
// TODO Log error
e.printStackTrace();
}
}
}
Calling code...
private class DeleteListener implements ClickListener {
public void onClick(Widget sender) {
DeleteSearchServiceAsync dss = DeleteSearchService.Util.getInstance();
SearchBean bean = buildBeanFromGUI();
dss.delete(bean, new AsyncCallback<Void>(){
//#Override
public void onFailure(Throwable caught) {
// TODO log
SearchNotDeleted snd = new SearchNotDeleted();
snd.show();
}
//#Override
public void onSuccess(Void result) {
SearchDeleted sd = new SearchDeleted();
sd.show();
searchDef.getParent().removeFromParent();
}
});
}
}
I know I'm a jerk for posting like 500 lines of code but I've been staring at this since yesterday and can't figure out where I'm going wrong. Maybe a 2nd set of eyes would help...
Thanks,
brian
LGTM I'm afraid.
Are you using the hosted mode or a full-fledged browser? You can try switching and see if it helps.
Also, it might help listening to that //TODO and perform a GWT.log when onFailure is invoked.