GWT RPC mechanism how to use non void return type - gwt

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>>

Related

Unsubscribing from RxJava2/RxAndroid PublishSubject

I'm trying to replace EventBus with RxAndroid.
I want pageable fragments to subscribe/unsubscribe to an event source, these fragments get created and discarded relatively quickly, depending on how fast the user slides to a new page.
In EventBus I was able to add an decorated callback method (ie #Subscribe(threadMode = ThreadMode.MAIN)) and register/unregister in the onStart/onStop methods of the fragment.
With RxJava2 I now create a PublishSubject object in a class
public static PublishSubject<List<Long>> m_psUpdatedDays = PublishSubject.create();
public static void publishUpdatedDays(List<Long> lDay) {
m_psUpdatedDays.onNext(lDay);
}
and subscribe to this publisher in another class by calling the following in the Fragment's onStart method:
m_psUpdatedDays.observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<List<Long>>() {
#Override public void onSubscribe(Disposable d) {}
#Override public void onNext(List<Long> longs) {
...
Update Fragment UI here
...
}
#Override public void onError(Throwable e) {}
#Override public void onComplete() {}
});
My question is how can I unsubscribe this new Observer when the Fragment's onStop method is called by the system?
Do I need to store the Disposable object which I get in the onSubscribe and then call .dispose() on it in the onStop method?
You can make use of a CompositeDisposable object, which can keep a list of disposables and all of them can be disposed together.
Create a CompositeDisposable instance in the base fragment level, keep on adding your disposables into it.
public abstract class BaseFragment extends Fragment {
protected CompositeDisposable mCompositeDisposable = new CompositeDisposable();
#Override
public void onPause() {
super.onPause();
mCompositeDisposable.clear();
//clear will clear all, but can accept new disposable.
// You can call it on `onPause` or `orDestroyView` events.
}
#Override
public void onDestroy() {
super.onDestroy();
mCompositeDisposable.dispose();
//dispose will clear all and set isDisposed = true, so it will not accept any new disposable
}
}
In your fragments, subscribe to the Observable using the subscribeWith method, which gives you a disposable instantly and this disposable you can dispose later in the onPause or onDestroy events (wherever you want)
public class MyFragment extends BaseFragment {
#Override
public void onStart() {
super.onStart();
Disposable disposable = m_psUpdatedDays.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<List<Long>>() { // Use `subscribeWith` instead of `subscribe`, which will give you back the disposable , which can be disposed later
#Override
public void onNext(List<Long> longs) {
// Update Fragment UI here
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
mCompositeDisposable.add(disposable); // add the disposable to the disposable list
}
}

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.)

GWT RPC call in onModuleLoad Implementation Failure

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());
}
});
}
}

Will an gwt rpc call ALWAYS callback to either my onsuccess or onfail methods?

I have implemented the suggestion in this post and disable my button after the the first click. How to prevent DoubleSubmit in a GWT application?
What i want to know is with my button reenabled in both my fail and success methods will it always get reenabled. Also is there any place i can put some code that i always want executed when the server replies as opposed to duplicating it in both fail and success methods
I do think that either onSuccess() or onFailure() will be called every time.
As for having a place where you can put code that will always run when getting a response to the server you could just create an AsyncCallback which has the code in it's onFailure() and onSuccess() methods. Then you can just extend that AsyncCallback everytime you create an AsyncCallback.
public MyAsyncCallback<T> extends AsyncCallback<T>(){
#Override
public void onFailure(Throwable caught){
//Do something
onResponse()
failed(caught);
}
#Override
public void onSuccess(T result){
//Do something
onResponse()
succeeded(result);
}
public void onResponse(){
// Do something or nothing by default
}
public abstract void failed(Throwable caught);
public abstract void succeeded(T result);
};
Whenever you want to create an AsyncCallback just use MyAsyncCallback:
AsyncCallback callback = new MyAsyncCallback(){
#Override
public void failed(Throwable caught){
//Do something
}
#Override
public void succeeded(T result){
//Do something
}
// Optionally override onResponse() if needed
#Override
public void onResponse(){
//Do something
}
}

Whats the best way to invoke a method by Reflection in GWT

What’s the best way to invoke a method by reflection using GWT, I know that there are some frameworks like "GWT Reflection" but I really want to hear some feedback about this.
How is the best way to convert something like this:
GreetingServiceAsync service = GWT.create(GreetingService.class);
AsyncCallback callBack = new AsyncCallback< Void>() {
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(Void result) {
}
};
service.doSomething(callBack);
in:
GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
String methodName = “doSomething”;
Object service;
AsyncCallback callBack = new AsyncCallback< Void>() {
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(Void result) {
}
};
/*somehow invoke by reflection*/
Class<?> c = Class.forName(GreetingServiceAsync.class.getName());
Method method = c.getMethod(methodName, AsyncCallback.class);
method.invoke (service, callBack);
Many thanks,
Luis.
Javascript 101 - there is no concept of reflection. GWT java translates to javascript. So gwt does not provide reflection support. Every other library that states gwt reflection in their homepage are just addressing a corner functionality and mis-stating their feature.