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.
Related
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.)
We are planning on using Jersey's reference implementation for our REST APIs. As a prototype effort, I was also playing around with the ContainerRequestFilters and I implemented multiple of them. Is there a way in which we can control the order in which these filters are executed?
The scenario that I am thinking over here is to ensure that the security filter must be the first one to run, and if required establish the SecurityContext and then execute other filters.
Yes you can control this with the javax.annotation.Priority attribute and the default javax.ws.rs.Priorities. For example if you wanted:
Logging filter always runs first
Authentication filter should run next
Authorization filter should run next
Custom filter should always run after others
You could do:
#Priority(Integer.MIN_VALUE)
public class CustomLoggingFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
// DO LOGGING HERE, THIS RUNS FIRST
}
}
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
String authHeader = requestContext.getHeaderString(HttpHeaders.WWW_AUTHENTICATE);
// DO AUTHENTICATION HERE, THIS RUNS SECOND
}
}
#Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
String authHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// DO AUTHORIZATION HERE, THIS RUNS THIRD
}
}
#Priority(Priorities.USER)
public class MyAwesomeStuffFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
// DO AWESOME STUFF HERE, THIS RUNS LAST
}
}
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
}
}
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>>
Doing my app, I got bored from always implement the same default error treatment (show a message, caught.printstacktrace and etc..) in the asynccallback onfailure.
I wonder if you can make a generic treatment or standard treatment, something like that.
Thanks.
I assume you are using standard GWT-RPC. Something like this might help
public abstract class AbstractCallBack<T> implements AsyncCallback<T>{
#Override
public void onFailure(Throwable caught) {
//Default error Handling code goes here
}
}
And whenever you use your service instead of instantiating an AsyncCallback you can instantiate this class and have generalized error handling.
SomeServiceAsync service = GWT.create(SomeService.class);
service.someMethod("Hello!", new AbstractCallBack<String>() {
#Override
public void onSuccess(String result) {
// TODO Auto-generated method stub
}
});