
google-web-toolkit - issue #6234
Support RequestFactory service inheritance on the client
Found in GWT Release (e.g. 1.5.3, 1.6 RC): 2.1 and later
Encountered on OS / Browser (e.g. WinXP, IE6-7, FF3): all
Detailed description (please be as specific as possible): Issue 5807 made it possible to inherit methods from a service base class on the server side; however, on the client side you must still declare inherited methods in each service interface because RequestFactory currently sends the name of the class in which a service method is declared. In order to support client-side inheritance, it should send the classname of the RequestContext actually being invoked, which may be a subclass of the RequestContext in which a method is declared.
Shortest code snippet which demonstrates issue (please indicate where actual result differs from expected result): It would be great for writing generic DAOs if we could say something like
@BaseService // tell generator this isn't intended to be directly instantiable public interface GenericDAORequestContext<T> extends RequestContext { Request<List<T>> listAll(); Request<Void> put(T obj); }
@Service(value = PersonDao.class, locator = DaoServiceLocator.class) interface PersonRequestContext extends GenericDAORequestContext<PersonProxy> { // Only Person-specific methods required here Request<Void> doSomethingSpecific(PersonProxy p); }
Workaround if you have one: none. If you implement a method in a service base class on the server side, you must declare it in the RequestContext interface for each service that inherits it.
Links to relevant GWT Developer Forum posts: See http://code.google.com/p/google-web-toolkit/issues/detail?id=5807 for prior fix on the server side.
Comment #1
Posted on Apr 4, 2011 by Swift KangarooIt would be great to see this fixed. Currently I need to copy and paste quite a lot of code because of this ... and I really really don't like to copy and paste code. Is there a chance that this could make it into 2.3?
Comment #2
Posted on Apr 10, 2011 by Swift KangarooI was working on a patch for this: http://gwt-code-reviews.appspot.com/1411802/
I was not able to set up a local environment in a reasonable amount of time, so I don't know if this is working or not.
Comment #3
Posted on Apr 11, 2011 by Swift BirdAny ETA on this?
Comment #4
Posted on Apr 11, 2011 by Swift KangarooI would like to know that, too. I was hoping that it could be fixed in 2.3
Comment #5
Posted on Apr 28, 2011 by Swift KangarooMy patch is not going to work. I am going to stop to work on this patch. I hope that someone who actually knows the code is going to take this one on.
Comment #6
Posted on Jun 1, 2011 by Quick OxInitial work on this patch needs some breaking, though minor, changes to the ServiceLayer since several of the resolveX() can no longer depend on requestContextMethod.getDeclaringType() == requestContext.
Comment #7
Posted on Jun 2, 2011 by Quick OxComment #8
Posted on Jun 9, 2011 by Quick Oxr10311
For the release notes:
Several of the ServiceLayer.resolveX() method signatures have changed in this release. These changes were made in order to allow the use of obfuscated type and operation tokens to reduce payload and generated JS size and to allow the use of overloaded method names in RequestContext subtypes. Users who have written their own ServiceLayerDecorator subclasses that override any of the resolveX() methods will need to modify their code to conform to the new API. In general, the expected behavior of the resolveX() methods is unchanged. Users who need to retain compatibility with 2.3 and 2.4 RequestFactory server code can leave methods with the old signatures in place, removing any @Override annotations.
Comment #9
Posted on Jun 17, 2011 by Swift KangarooI just tried the 2.4.0-beta and it is still appears broken with my code. I am invoking a method from a GenericListRequest, but invoke it out of a PersonListRequestContext.
It seems like the makeRequestData method in the auto-generated PersonListRequestContextImpl generates a bad RequestData object. The operation string inside the RequestData object still reads: '....GenericListRequest::listAll'. That indicates that the RequestMethod object didn't get generated quite right for the listAll method of the PersonListRequestContext.
I am going to take a closer look to see if I can get more info. Also, I could upload my code to github, if that would be helpful.
Comment #10
Posted on Jun 17, 2011 by Helpful Monkey(No comment was entered for this change.)
Comment #11
Posted on Jun 17, 2011 by Quick OxMoving Fixed -> FixedNotReleased since 2.4 hasn't shipped yet.
Comment #12
Posted on Jun 27, 2011 by Swift KangarooAfter digging a bit deeper, I see that the problem still lies in com.google.web.bindery.requestfactory.gwt.rebind.model.RequestFactoryModel line 209 and its call to com.google.web.bindery.requestfactory.gwt.rebind.model.RequestMethod.setDeclarationMethod. The RequestMethod.Builder had no knowledge about the PersonListRequestContext. It only knows that the method is enclosed in the GenericListRequest.
I am not sure how this is supposed to be fixed. Is there a new annotation that I am missing?
Comment #13
Posted on Jun 27, 2011 by Swift KangarooAddition to the previous comment:
I built gwt from the sources in my local repo:
URL: http://google-web-toolkit.googlecode.com/svn/tags/2.4.0.beta Repository Root: http://google-web-toolkit.googlecode.com/svn Repository UUID: 8db76d5a-ed1c-0410-87a9-c151d255dfc7 Revision: 10399
Comment #14
Posted on Aug 30, 2011 by Swift Ox(No comment was entered for this change.)
Comment #15
Posted on Sep 7, 2011 by Quick RabbitIs there anything new on this? I still get "Could not find matching method in " when I try to do this in 2.4 rc1. It'd also be nice if the logging could say which method it's failing on getting.
Comment #16
Posted on Sep 7, 2011 by Swift RhinoIt depends what you want to achieve.
For composition (i.e. the same batch –HTTP request– dispatched on several difference services), you should use the new .append(RequestContext) method of RequestContext (that is, you compose several contexts together in the same "batch").
For mix-in (which is actually issue 6035), simply extend other interfaces, and the method will be looked up on the @Service corresponding to the bottom-most interface (contrary to before, where it was looked up on the @Service corresponding to the interface where the method was defined, which implicitly allowed composition that way).
Comment #17
Posted on Sep 7, 2011 by Grumpy HippoReleased in 2.4
Comment #18
Posted on Sep 7, 2011 by Quick RabbitI'm trying to use mix-ins with generics as in the original issue detail (although without the 'extends RequestContext' on the mix-in interface and on the actual implementation). However, that always leads to it complaining that it "Could not find matching method" in my server object. It does not say which one, but gives some possible ones as a list. Once I get rid of it extending the mix-in portion, it goes back to working. Doesn't matter if I override the methods super interface or not making it specifically use the generic type passed into it. Somewhere it also complains that "java.lang.Object has no mapping to a domain type (e..g. @ProxyFor or @Service)" and "Type must be an interface".
Comment #19
Posted on Oct 8, 2011 by Swift MonkeyNot sure if this is how they designed it, but I added @SkipInterfaceValidation to the generic mix-in interface. It ends up looking like:
@SkipInterfaceValidation public interface PaginationRequest extends RequestContext {
Request<List<T>> paginate(int offset, int limit, String sortColumn,
boolean isSortAscending, List<FilterProxy> filters);
Request<Integer> count(List<FilterProxy> list);
}
@Service(value=UserService.class, locator=MyServiceLocator.class) public interface UserRequest extends PaginationRequest, SomeOtherMixin { // Additional request specific methods here }
I imagine what I am doing is disabling the interface validation and this is not as they designed it. But since it doesnt seem to be working and there are no other work-arounds, this will have to do.
Comment #20
Posted on Nov 7, 2011 by Happy RhinoIt still doesn't work. Validator finds no bug, but when I want to execute request it returns "Could not find matching method"
Comment #21
Posted on Nov 7, 2011 by Swift RhinoFYI, the test related to this issue are http://code.google.com/p/google-web-toolkit/source/browse/tags/2.4.0/user/test/com/google/web/bindery/requestfactory/shared/ServiceInheritanceTest.java
Generics are indeed not supported; jtuchscherer reported it as issue 6642.
Comment #22
Posted on Dec 28, 2011 by Happy BirdComment deleted
Status: Fixed
Labels:
Milestone-2_4
ReleaseNote-BreakingChange