| /////////////////////////////////////////////////////////////// |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| /////////////////////////////////////////////////////////////// |
| |
| [[tut-composites-step8,Step 8 - Generic Mixins]] |
| = Step 8 - Generic Mixins = |
| |
| Previous step was <<tut-composites-step7>>. |
| |
| In this step we will look at how to use generic Fragments. So far all Fragments, i.e. the Concerns, SideEffects, |
| and Mixins, have directly implemented the domain interface. But sometimes it is useful to be able to provide a generic |
| implementation of an interface. An example of this is the HelloWorldState interface. Since it only handles properties, |
| and the old version used the JavaBean rules for naming getters and setters we could create a mixin that handles |
| invocations of such methods automatically for us by storing the properties in a map and use the methods to look them up. |
| |
| Implementing a generic Fragment is done by creating a class that implements the interface |
| java.lang.proxy.InvocationHandler. This has a single "invoke" method which is passed the object that was invoked (the |
| TransientComposite in this case), the method, and the arguments. The Fragment is then allowed to implement the method |
| any way it wants. |
| |
| Since interfaces with only Properties is such a common case Zestâ„¢ already has a generic Mixin that implements the |
| Properties management described above, but for the builtin Property type instead of the getter/setter variant. The |
| class is aptly named PropertyMixin. |
| |
| While we could use it, for now we will implement it ourselves to get a feel for how generic Mixins work. |
| |
| Steps for this tutorial: |
| |
| - Remove the HelloWorldStateMixin |
| - Add a GenericPropertyMixin, and have it implement InvocationHandler |
| - Inject "@State StateHolder state" in the mixin. The StateHolder interface will give you access to the Properties for the TransientComposite which Zestâ„¢ manages for you |
| - On call to invoke(), delegate to the StateHolder interface to get the Property for the invoked method |
| - Add an @AppliesTo annotation to the Mixin and implement the AppliesToFilter with a rule that matches only methods that return Property values. |
| - Add the mixin to the TransientComposite. |
| |
| == Solution == |
| |
| If you have successfully completed the task, you should end up with the following artifacts; |
| |
| These ones remain unchanged: |
| |
| - +HelloWorldBehaviour.java+ |
| - +HelloWorldState.java+ |
| |
| *GenericPropertyMixin.java* |
| [snippet,java] |
| ---- |
| source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/GenericPropertyMixin.java |
| tag=solution |
| ---- |
| |
| *HelloWorldBehaviourMixin.java* |
| [snippet,java] |
| ---- |
| source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldBehaviourMixin.java |
| tag=solution |
| ---- |
| |
| *HelloWorldComposite.java* |
| [snippet,java] |
| ---- |
| source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldComposite.java |
| tag=solution |
| ---- |
| |
| Next step is <<tut-composites-step9>> |