Re: component inheritance T5.2.5 (SOLVED!)
On Mon, 15 Aug 2011 14:46:03 -0300, Jens Breitenstein wrote: Hi Thiago!! I found a workaround!!! Definitely ComponentInstantiatorSource is your friend. Decorating this one allows me exactly to replace the componts I want to change. It's an internal service (notice it's inside a package named internal, directly or not) and no guarantee about it even existing in newer versions is given. Now we have a nice feature request. :) But bind() is for services, not components. Very different beasts. I know bind is for services, let's call it bindComponent(O, D)// original type, derived type I'm saying that replacing one component name by anoter component class is a bad idea, but introducing new syntax just for components in an interface named ServiceBinder is not a good idea. We can create a service for it and contribute configuration to it as any other service. But it can be emulated by decorating one service and 10 lines of code? You're comparing orange to apples here. It's not emulation at all. Tapestry is comprised of many services and what you call emulation is absolutely ordinary advice or decoration of one of them. Services are handled by Tapestry-IoC in a way completely different from Tapestry(-core) handling components and it seems you haven't realizad this yet. Tapestry-the-web-framework and Tapestry-IoC are different things, even when both are similarly named and the latter uses the former. why should T5 not able to do it? I guess this is a useful feature for others, too. If you're asking about having some out-of-the-box way in Tapestry for replacing components, I agree with you. File a JIRA for it. Now we have a full OO stack using inheritance and default injection even for components, message catalogs, spring/t5 services, hibernate pojo's without one line of xml. Maybe one of you guys can convince Howard at least to think about it? I agree with your request, but I disagree on the solution. And Howard isn't the only committer in the team, even he being the creator and a natural leader: http://tapestry.apache.org/about.html (Taha Hafeez will be a committer soon! Yay!) -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: component inheritance T5.2.5 (SOLVED!)
Hi Thiago!! I found a workaround!!! Definitely ComponentInstantiatorSource is your friend. Decorating this one allows me exactly to replace the componts I want to change. code: I saw you pasted it but did not see a difference. I'll stick it in SmartSync later :-), maybe I am near to blindness and need beer to activate self-healing Now we have a nice feature request. :) But bind() is for services, not components. Very different beasts. I know bind is for services, let's call it bindComponent(O, D)// original type, derived type I can't see a difference to @InjectComponent private A _a;// <-- injection MAGIC, why not a BderivedFromA because of bind(ComponentA.class, ComponentBderivedFromA.class)? or am I totally wrong? In this case, this is vry different than components. Components (and pages and mixins) are loaded by the Tapestry classloader and changed in memory for a very specific scenario (webapps). Services aren't. But it can be emulated by decorating one service and 10 lines of code? why should T5 not able to do it? I guess this is a useful feature for others, too. Now we have a full OO stack using inheritance and default injection even for components, message catalogs, spring/t5 services, hibernate pojo's without one line of xml. Maybe one of you guys can convince Howard at least to think about it? Thanks for your help Jens p.s. it's still unclear why I only see a bunch of classes. But my customer kills me if I do not make progress, so I take the work-around for now - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: component inheritance T5.2.5
On Mon, 15 Aug 2011 13:26:11 -0300, Jens Breitenstein wrote: Thiago, Hi! do you use multiple modules? Yes! Lots of them! Maybe this screws up our Modules (@SubModule to be precise), or whatever? How are you adding this other modules' pages and components? What are their prefix? this list grows slowly but only contains classes from the current module, non of the base components from other jars are ever mentioned, still. And this is regardless in which module I place the advice, result is always the same. Are you requesting pages that contain these base components? You wrote my original advise contains some bugs ... can you please paste the fixed version you used for your test so I can see all mistakes I made? That's in my last e-mail. A forgotton Annotation? More like annotations badly used . . . Would it not be nice to write bind(ComponentA.class, ComponentBderivedFromA.class) and our sophisticated class factory, called tapestry-ioc, injects ComponentBderivedFromA whenever ComponentA or ComponentBderivedFromA is used as member? Now we have a nice feature request. :) But bind() is for services, not components. Very different beasts. I can't see a difference to @InjectComponent private A _a;// <-- injection MAGIC, why not a BderivedFromA because of bind(ComponentA.class, ComponentBderivedFromA.class)? or am I totally wrong? In this case, this is vry different than components. Components (and pages and mixins) are loaded by the Tapestry classloader and changed in memory for a very specific scenario (webapps). Services aren't. -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: component inheritance T5.2.5
Thiago, do you use multiple modules? - we are building running T5 apps per layer - each layer is build by mvn thus containing a root pom. - all layers may depend on jars from "upper" layers to assemble a new T5 app (just by jar dependencies). - we have a module per layer and annotate it by @SubModule( { CoreModule.class, SecurityModule.class }) for example Maybe this screws up our Modules (@SubModule to be precise), or whatever? Console output of my advise is (compacted by removing duplicate entries): # Activity # outputraw # loop # if # layout/shopheader # layout/header # banners # layout/footer # tracking # layout/VerticalsMenu # actionlink this list grows slowly but only contains classes from the current module, non of the base components from other jars are ever mentioned, still. And this is regardless in which module I place the advice, result is always the same. You wrote my original advise contains some bugs ... can you please paste the fixed version you used for your test so I can see all mistakes I made? A forgotton Annotation? I promise to not bother you again with this topic, because I am near to use aspectj to modify the classes after compilation :-) Yes, sledgehammer approach! @T5 experts, maybe "OT - feature wish": Would it not be nice to write bind(ComponentA.class, ComponentBderivedFromA.class) and our sophisticated class factory, called tapestry-ioc, injects ComponentBderivedFromA whenever ComponentA or ComponentBderivedFromA is used as member? I mean, can't we just treat the type similar to interfaces in conjunction with services? We are not write something like private A _a = new A(); in Tapestry. What we would have written in the good old days might be private A _a = ServiceLocater.get(A.class);// which might have returned a BderivedFromA but thanks to spring and T5-ioc we write @Inject private IService _service; I can't see a difference to @InjectComponent private A _a;// <-- injection MAGIC, why not a BderivedFromA because of bind(ComponentA.class, ComponentBderivedFromA.class)? or am I totally wrong? Jens - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: component inheritance T5.2.5
Sorry Thiago that this simple task turns into an endless story... I've tried it, and even clicking all pages does not call my CCR. When looking at CCRImpl everything is cached after "rebuild". When setting a break point in CCRImpl.resolveComponentTypeToClassName:430 it's hit around 40 times not more. And it only requests components from my module nothing from my base modules. "fillNameToClassNameMap" uses a "classNameLocator" which indeed provides all classes including my components. But there is no call to "resolve" thus no chance to provide something different. There is a 3rd solution based on manipulating the field type before tapestry does it's magic I was looking at so lets assume I am about *t*o despair... Unfortunately I can not change the field type from A to B or inject a valid B component instance @Decorate(serviceInterface = ComponentClassTransformWorker.class) public static Object customComponentClassTransformWorker(final ComponentClassTransformWorker delegate) { return new ComponentClassTransformWorker() { public void transform(final ClassTransformation transformation, final MutableComponentModel model) { if (A.class.getName().equals(transformation.getClassName())) { final TransformField basketItemComponentField = transformation.getField("_a"); final B b = ??? TODO: CREATE A FULLY INITIALIZED T5 COMPONENT INSTANCE; basketItemComponentField.inject(b); } delegate.transform(transformation, model); } }; } Let's assume I tried injectIndirect but then T5 complains about "has already had write access replaced". Jens Am 15.08.11 13:00, schrieb Thiago H. de Paula Figueiredo: On Sun, 14 Aug 2011 19:06:25 -0300, Jens Breitenstein wrote: ok, next step... Hi! this code below shows me all components from my current module/layer, but the classes I want to "cheat" are not mentioned. Is it possible tapestry creates a ComponentClassResolver per module? No. It's a singleton service. Definitely the sysout only shows a minor amount of components and not all components used/existing in all layers. It's just invoked for the components in the page you're requested, not all components every time. Request every page and you'll see all component names printed. And @Order annotation is of no help, too. It's useful for when you have more than one advice for the same service, and this is not your case.
Re: component inheritance T5.2.5
On Sun, 14 Aug 2011 19:06:25 -0300, Jens Breitenstein wrote: ok, next step... Hi! this code below shows me all components from my current module/layer, but the classes I want to "cheat" are not mentioned. Is it possible tapestry creates a ComponentClassResolver per module? No. It's a singleton service. Definitely the sysout only shows a minor amount of components and not all components used/existing in all layers. It's just invoked for the components in the page you're requested, not all components every time. Request every page and you'll see all component names printed. And @Order annotation is of no help, too. It's useful for when you have more than one advice for the same service, and this is not your case. -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: component inheritance T5.2.5
ok, next step... this code below shows me all components from my current module/layer, but the classes I want to "cheat" are not mentioned. Is it possible tapestry creates a ComponentClassResolver per module? Definitely the sysout only shows a minor amount of components and not all components used/existing in all layers. And @Order annotation is of no help, too. Seems I am missing something fundamentally? Jens @Advise(serviceInterface = ComponentClassResolver.class) @Match("resolveComponentTypeToClassName") public static void adviceComponentClassResolverResolveComponentTypeToClassName(final MethodAdviceReceiver receiver) { final MethodAdvice methodAdvise = new MethodAdvice() { public void advise(final Invocation invocation) { System.out.println(invocation.getMethodName() + " " + invocation.getParameter(0)); invocation.proceed(); } }; boolean advised = false; for (final Method method : receiver.getInterface().getMethods()) { if (method.getName().equals("resolveComponentTypeToClassName")) { receiver.adviseMethod(method, methodAdvise); advised = true; break; } } if (!advised) { throw new IllegalStateException("ComponentClassResolver does not provide a method [resolveComponentTypeToClassName]"); } } Am 14.08.11 15:28, schrieb Thiago H. de Paula Figueiredo: On Sun, 14 Aug 2011 10:03:37 -0300, Jens Breitenstein wrote: Hi Thiago! Hi! Thanks for your response but I do not get you. What do you mean by "checking the generated xml"? HTML, not XML. Open the page in your browser of choice then use the command "view source". Unfortunately in my special case I have to override some hardcoded component functionality from an "upper layer". But just creating a derived class seems not to be an option as tapestry creates the components based on the field type Correct, as in any Java code. ;) and how should it be aware of my derived component? You can advise or decorate the ComponentClassResolver service through Tapestry-IoC, specifically the resolveComponentTypeToClassName() method. It's exactly the place Tapestry uses to map component names to component classes. By advising or decorating this method, you can do any name->component class mapping you want. Sorry english is not my native language Nor mine. :) so hopefully the description is understandable. It is. :) - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: component inheritance T5.2.5
Hi Thiago! Thanks for your response but I do not get you. What do you mean by "checking the generated xml"? Maybe I have to provide some more info about what I am trying to achieve... We are using several layers (different SVN's, MVN projects) to create customized applications just by using java OO principles (means we override spring services or hibernate entities per layer, override tml's, thanks to Igor and you we override global message catalogs aso). Each layer provides it's own module thus is a fully running T5 app and we can reuse the functionality from each layer without copy and paste. Unfortunately in my special case I have to override some hardcoded component functionality from an "upper layer". But just creating a derived class seems not to be an option as tapestry creates the components based on the field type and how should it be aware of my derived component? I found an InjectionProvider but this class only injecting services, not components. To make tapestry aware of my derived class I am quite sure I have to specify it somewhere in the ioc config section. So the ideal solution would be a "component inject service" which I can use to return "B" in case an instance of "A" is requested... Sorry english is not my native language so hopefully the description is understandable. I mean worst case workaround might be to override the tml, copy and paste the full content and replace the compent "A" by "B". But intercepting a service would allow me (and all of us) to transparently inject derivded components without the need of touching tml's. Jens Am 14.08.11 14:07, schrieb Thiago H. de Paula Figueiredo: On Sat, 13 Aug 2011 09:26:27 -0300, Jens Breitenstein wrote: hi All! Hi! Have you checked the generated HTML? I have some trouble concerning component inheritance. My scenario is something like: A.tml http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"; xmlns:p="tapestry:parameter" class="mini-basket-items"> A.class -- public class A { public String getValueForA() { return "a"; } } B.class -- public class B extends A { public String getValueForA() { return "b"; } } there is no tml provided by B thus A's tml should be fully reused. the expression "valueForA" always returns "a" and the overridden method in class "B" is never called. is there additional configuration required to make it working? Thanks again Jens - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: component inheritance T5.2.5
On Sat, 13 Aug 2011 09:26:27 -0300, Jens Breitenstein wrote: hi All! Hi! Have you checked the generated HTML? I have some trouble concerning component inheritance. My scenario is something like: A.tml http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"; xmlns:p="tapestry:parameter" class="mini-basket-items"> A.class -- public class A { public String getValueForA() { return "a"; } } B.class -- public class B extends A { public String getValueForA() { return "b"; } } there is no tml provided by B thus A's tml should be fully reused. the expression "valueForA" always returns "a" and the overridden method in class "B" is never called. is there additional configuration required to make it working? Thanks again Jens - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. Consultor, desenvolvedor e instrutor em Java, Tapestry e Hibernate http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
component inheritance T5.2.5
hi All! I have some trouble concerning component inheritance. My scenario is something like: A.tml http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"; xmlns:p="tapestry:parameter" class="mini-basket-items"> A.class -- public class A { public String getValueForA() { return "a"; } } B.class -- public class B extends A { public String getValueForA() { return "b"; } } there is no tml provided by B thus A's tml should be fully reused. the expression "valueForA" always returns "a" and the overridden method in class "B" is never called. is there additional configuration required to make it working? Thanks again Jens - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org