You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@aries.apache.org by David Jencks <da...@yahoo.com> on 2010/01/10 19:32:37 UTC

Blueprint NamespaceHandler issues

I've been working on converting xbean-spring to xbean-blueprint and  
have run into a couple of issues that would be more easily fixed in  
blueprint.  I don't see any bad effects from the changes I'm proposing  
but since I'm not that familiar with blueprint wanted to discuss them  
before committing.

1. (ARIES-111).  ParserContext.parseElement currently requires you to  
specify very precisely the type you expect an element to parse into,  
and is inconsistent about whether it checks that the element is in the  
blueprint namespace and whether it looks for suitable  
NamespaceHandlers if it is not.  For instance asking for a  
BeanProperty does check for blueprint namespace whereas asking for  
BeanMetadata does not.  There might well be a more general approach  
but for my purposes simply allowing Metadata.class as the desired type  
and feeding the request to Parser.parseValueGroup parses all blueprint  
elements I need and feeds the request to the appropriate  
NamespaceHandler.

2. (ARIES-110)  equals/hashcode methods on Metadata classes.  xbean- 
blueprint does some fancy stuff with maps that involve figuring out  
whether a key is already present in a map.  This means you have to be  
able to figure out when keys are "equal".  I think this makes sense  
for a few metadata types so I'm proposing implementing the methods in  
these:

RefMetadataImpl
ValueMetadataImpl
ServiceReferenceMetadataImpl
ReferenceMetadataImpl

This equality test would be fairly easy to implement in the  
NamespaceHandler rather than the classes, so if people think that  
equals should mean == for these I won't object.

Comments?

thanks
david jencks


Re: Blueprint NamespaceHandler issues

Posted by David Jencks <da...@yahoo.com>.
inline...

On Jan 10, 2010, at 1:22 PM, The Dweller wrote:

> Just a couple of quick responses, I'll look a bit more tomorrow..
>
> 1. ARIES-111
> In general namespaces are enforced by the schema, and outside of the
> parseElement call, BeanMetata data has its namespace checked & handled
> correctly. The parseElement call would only be invoked by a custom  
> namespace
> handler, at which point you are now parsing a non-blueprint-namespaced
> element (or attribute), and it's content is under your control.  
> That's to
> say the namespace handler should know what content it expects,  
> blueprint or
> not, and had to supply a schema to that effect back to the parser.
>
> The current approach does not lend well though to being able to ask  
> the
> parser to 'please just handle this, and anything inside it', which  
> would
> make sense if you were including xsd:any within your element from your
> custom schema, _and_ that you intended that 'any' content to contain  
> yet
> more blueprint, or blueprint-instance-extended-namespace content..  
> I'd be
> interested in how you'd use nested blueprint metadata like this, as I
> suspect currently that would involve a bean processor, or component
> definition registry processor (or, just possibly a rather twisted
> passthrumetadata, or componentfactorymetadata). So I can see that  
> there
> could be value to either adding a new method to the parser context, or
> updating the current one.
>
> The current method however does allow the slight trick where you can  
> take a
> non blueprint element, and have it parse as if it were a given  
> blueprint
> element, by passing the appropriate metadata and the element, which  
> can be
> an interesting way to get blueprint to give you back information you  
> wish to
> use. For example, you could have an 'CustomBeanMetadata' element  
> that you
> declare with the appropriate schema to accept the content of a  
> regular bean,
> plus a few other bits you care for. When the ns handler is invoked  
> for the
> CustomBeanMetadata element, you can pass it back to the parsercontext,
> asking it to be parsed as a bean. Then you can modify the data, or  
> perform
> whatever action the ns handler was there for, again I'm interested  
> in any
> scenarios you think of around this sort of usage.
>

basically I want to make what you describe as a "trick" work better,  
more often.  In a related issue I don't see why the root element  
should need to be in the blueprint namespace if an appropriate  
NamespaceHandler is registered.  xbean-spring has been used in spring  
for years by projects such as activemq to do stuff like this.  Since  
we might have an opportunity to make it work more smoothly in  
blueprint.... I think this is a good time to discuss it.

Anyway.... here are some plans that should give the same bunch of  
metadata, in various combinations of blueprint and (sample) xbean- 
blueprint configurations:

pure blueprint:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

   <!--  tests using nested beans -->

   <bean id="restaurant"
     class="org.apache.xbean.blueprint.example.RestaurantService">
     <property name="serviceName">
       <bean class="javax.xml.namespace.QName">
         <argument value="http://acme.com"/>
         <argument value="xyz"/>
         <argument value="foo"/>
       </bean>
     </property>
     <property name="favourite">
       <bean class="org.apache.xbean.blueprint.example.PizzaService">
         <property name="topping" value="Salami" />
         <property name="cheese" value="Edam" />
         <property name="size" value="17" />
       </bean>
     </property>
     <property name="dinnerMenu">
       <list>
         <bean class="org.apache.xbean.blueprint.example.PizzaService">
           <property name="topping" value="Ham" />
           <property name="cheese" value="Mozzarella" />
           <property name="size" value="15" />
         </bean>
         <bean class="org.apache.xbean.blueprint.example.PizzaService">
           <property name="topping" value="Eggs" />
           <property name="cheese" value="Mozzarella" />
           <property name="size" value="16" />
         </bean>
       </list>
     </property>
     <property name="snackMenu">
       <set>
         <bean class="org.apache.xbean.blueprint.example.PizzaService">
           <property name="topping" value="Tofu" />
           <property name="cheese" value="Parmesan" />
           <property name="size" value="6" />
         </bean>
         <bean class="org.apache.xbean.blueprint.example.PizzaService">
           <property name="topping" value="Prosciutto" />
           <property name="cheese" value="Blue" />
           <property name="size" value="8" />
         </bean>
       </set>
     </property>
     <property name="lunchMenu">
       <list>
         <bean class="org.apache.xbean.blueprint.example.PizzaService">
           <property name="topping" value="Chicken" />
           <property name="cheese" value="Brie" />
           <property name="size" value="17" />
         </bean>
       </list>
     </property>
   </bean>


</blueprint>


nearly-pure xbean-blueprint (I think have the root element be in the  
foreign namespace should work)

<b:blueprint xmlns:b="http://www.osgi.org/xmlns/blueprint/v1.0.0"
              xmlns:p="http://xbean.apache.org/schemas/pizza"
              xmlns:foo="http://acme.com">

   <p:restaurant b:id="restaurant"
                 p:serviceName="foo:xyz"
                 p:uri="http://cheese.com">
     <p:dinnerMenu>
       <p:pizza p:myTopping="Ham" p:cheese="Mozzarella" p:size="15"/>
       <p:pizza p:myTopping="Eggs" p:cheese="Mozzarella" p:size="16"/>
     </p:dinnerMenu>

     <p:lunchMenu>
       <p:pizza p:myTopping="Chicken" p:cheese="Brie" p:size="17"/>
     </p:lunchMenu>

     <p:snackMenu>
       <p:pizza p:myTopping="Tofu" p:cheese="Parmesan" p:size="6"/>
       <p:pizza p:myTopping="Prosciutto" p:cheese="Blue" p:size="8"/>
     </p:snackMenu>

     <p:favourite>
       <p:pizza p:myTopping="Salami" p:cheese="Edam" p:size="17"/>
     </p:favourite>
   </p:restaurant>
</b:blueprint>


mixed:

<b:blueprint xmlns:b="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:foo="http://acme.com">

   <p:restaurant b:id="restaurant" xmlns:p="http://xbean.apache.org/schemas/pizza 
"
               p:serviceName="foo:xyz">
     <p:dinnerMenu>
       <p:pizza p:myTopping="Ham" p:cheese="Mozzarella" p:size="15"/>
       <b:bean class="org.apache.xbean.blueprint.example.PizzaService">
         <b:property name="topping" value="Eggs"/>
         <b:property name="cheese" value="Mozzarella"/>
         <b:property name="size" value="16"/>
       </b:bean>
     </p:dinnerMenu>

     <p:snackMenu>
       <p:pizza p:myTopping="Tofu" p:cheese="Parmesan" p:size="6"/>
       <p:pizza p:myTopping="Prosciutto" p:cheese="Blue" p:size="8"/>
     </p:snackMenu>

     <p:lunchMenu>
       <b:bean xmlns=""  
class="org.apache.xbean.blueprint.example.PizzaService">
         <b:property name="topping" value="Chicken"/>
         <b:property name="cheese" value="Brie"/>
         <b:property name="size" value="17"/>
       </b:bean>
     </p:lunchMenu>

     <p:favourite>
       <bean xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"  
class="org.apache.xbean.blueprint.example.PizzaService">
         <property name="topping" value="Salami"/>
         <property name="cheese" value="Edam"/>
         <property name="size" value="17"/>
       </bean>
     </p:favourite>
   </p:restaurant>
</b:blueprint>


If you want to look further, the code is at

https://svn.apache.org/repos/asf/geronimo/xbean/trunk/xbean-blueprint

The xml above is from the unit tests.

>
> 2. ARIES-110
> I wonder for the equals/hashcode case what you would do if you  
> encountered
> implementations of the Metadata interfaces that were not the  
> org.apache..
> impls. As any other namespace handler, or component definition  
> registry
> processor, could be creating instances of the blueprint api  
> interfaces that
> are not 'our' impls, and which may not implement a sensible equals /
> hashcode.

Hmm.... I wasn't really aware that you were supposed to be able to use  
your own metadata classes, since ParserContext has the method to  
create them for you.  Could be useful.....

So, it seems that the two reasonable solutions would be to get the  
spec to require metadata implementations to implement equals and  
hashcode appropriately, or to compare metadata object myself.  The  
former seems more reliable to me, as I'd guess that such non-aries  
metadata classes might have information in them that is not exposed by  
the various metadata interfaces that would lead an external equals  
method to give the wrong result.  Is this a reasonable fear?  Its  
certainly easy enough to write an external equals method.

thanks!
david jencks

>
> Regards,
> Ozzy
>
> On Sun, Jan 10, 2010 at 6:32 PM, David Jencks  
> <da...@yahoo.com>wrote:
>
>> I've been working on converting xbean-spring to xbean-blueprint and  
>> have
>> run into a couple of issues that would be more easily fixed in  
>> blueprint.  I
>> don't see any bad effects from the changes I'm proposing but since  
>> I'm not
>> that familiar with blueprint wanted to discuss them before  
>> committing.
>>
>> 1. (ARIES-111).  ParserContext.parseElement currently requires you to
>> specify very precisely the type you expect an element to parse  
>> into, and is
>> inconsistent about whether it checks that the element is in the  
>> blueprint
>> namespace and whether it looks for suitable NamespaceHandlers if it  
>> is not.
>> For instance asking for a BeanProperty does check for blueprint  
>> namespace
>> whereas asking for BeanMetadata does not.  There might well be a more
>> general approach but for my purposes simply allowing Metadata.class  
>> as the
>> desired type and feeding the request to Parser.parseValueGroup  
>> parses all
>> blueprint elements I need and feeds the request to the appropriate
>> NamespaceHandler.
>>
>> 2. (ARIES-110)  equals/hashcode methods on Metadata classes.
>> xbean-blueprint does some fancy stuff with maps that involve  
>> figuring out
>> whether a key is already present in a map.  This means you have to  
>> be able
>> to figure out when keys are "equal".  I think this makes sense for  
>> a few
>> metadata types so I'm proposing implementing the methods in these:
>>
>> RefMetadataImpl
>> ValueMetadataImpl
>> ServiceReferenceMetadataImpl
>> ReferenceMetadataImpl
>>
>> This equality test would be fairly easy to implement in the
>> NamespaceHandler rather than the classes, so if people think that  
>> equals
>> should mean == for these I won't object.
>>
>> Comments?
>>
>> thanks
>> david jencks
>>
>>


Re: Blueprint NamespaceHandler issues

Posted by The Dweller <ba...@gmail.com>.
Just a couple of quick responses, I'll look a bit more tomorrow..

1. ARIES-111
In general namespaces are enforced by the schema, and outside of the
parseElement call, BeanMetata data has its namespace checked & handled
correctly. The parseElement call would only be invoked by a custom namespace
handler, at which point you are now parsing a non-blueprint-namespaced
element (or attribute), and it's content is under your control. That's to
say the namespace handler should know what content it expects, blueprint or
not, and had to supply a schema to that effect back to the parser.

The current approach does not lend well though to being able to ask the
parser to 'please just handle this, and anything inside it', which would
make sense if you were including xsd:any within your element from your
custom schema, _and_ that you intended that 'any' content to contain yet
more blueprint, or blueprint-instance-extended-namespace content.. I'd be
interested in how you'd use nested blueprint metadata like this, as I
suspect currently that would involve a bean processor, or component
definition registry processor (or, just possibly a rather twisted
passthrumetadata, or componentfactorymetadata). So I can see that there
could be value to either adding a new method to the parser context, or
updating the current one.

The current method however does allow the slight trick where you can take a
non blueprint element, and have it parse as if it were a given blueprint
element, by passing the appropriate metadata and the element, which can be
an interesting way to get blueprint to give you back information you wish to
use. For example, you could have an 'CustomBeanMetadata' element that you
declare with the appropriate schema to accept the content of a regular bean,
plus a few other bits you care for. When the ns handler is invoked for the
CustomBeanMetadata element, you can pass it back to the parsercontext,
asking it to be parsed as a bean. Then you can modify the data, or perform
whatever action the ns handler was there for, again I'm interested in any
scenarios you think of around this sort of usage.


2. ARIES-110
I wonder for the equals/hashcode case what you would do if you encountered
implementations of the Metadata interfaces that were not the org.apache..
impls. As any other namespace handler, or component definition registry
processor, could be creating instances of the blueprint api interfaces that
are not 'our' impls, and which may not implement a sensible equals /
hashcode.

Regards,
Ozzy

On Sun, Jan 10, 2010 at 6:32 PM, David Jencks <da...@yahoo.com>wrote:

> I've been working on converting xbean-spring to xbean-blueprint and have
> run into a couple of issues that would be more easily fixed in blueprint.  I
> don't see any bad effects from the changes I'm proposing but since I'm not
> that familiar with blueprint wanted to discuss them before committing.
>
> 1. (ARIES-111).  ParserContext.parseElement currently requires you to
> specify very precisely the type you expect an element to parse into, and is
> inconsistent about whether it checks that the element is in the blueprint
> namespace and whether it looks for suitable NamespaceHandlers if it is not.
>  For instance asking for a BeanProperty does check for blueprint namespace
> whereas asking for BeanMetadata does not.  There might well be a more
> general approach but for my purposes simply allowing Metadata.class as the
> desired type and feeding the request to Parser.parseValueGroup parses all
> blueprint elements I need and feeds the request to the appropriate
> NamespaceHandler.
>
> 2. (ARIES-110)  equals/hashcode methods on Metadata classes.
>  xbean-blueprint does some fancy stuff with maps that involve figuring out
> whether a key is already present in a map.  This means you have to be able
> to figure out when keys are "equal".  I think this makes sense for a few
> metadata types so I'm proposing implementing the methods in these:
>
> RefMetadataImpl
> ValueMetadataImpl
> ServiceReferenceMetadataImpl
> ReferenceMetadataImpl
>
> This equality test would be fairly easy to implement in the
> NamespaceHandler rather than the classes, so if people think that equals
> should mean == for these I won't object.
>
> Comments?
>
> thanks
> david jencks
>
>