Export to GitHub

google-web-toolkit - issue #6234

Support RequestFactory service inheritance on the client


Posted on Apr 4, 2011 by Happy Cat

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 Kangaroo

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

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

Any ETA on this?

Comment #4

Posted on Apr 11, 2011 by Swift Kangaroo

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

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

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

http://gwt-code-reviews.appspot.com/1447815/

Comment #8

Posted on Jun 9, 2011 by Quick Ox

r10311

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 Kangaroo

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

Moving Fixed -> FixedNotReleased since 2.4 hasn't shipped yet.

Comment #12

Posted on Jun 27, 2011 by Swift Kangaroo

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

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

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

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

Released in 2.4

Comment #18

Posted on Sep 7, 2011 by Quick Rabbit

I'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 Monkey

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

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

FYI, 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 Bird

Comment deleted

Status: Fixed

Labels:
Milestone-2_4 ReleaseNote-BreakingChange