You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jaxme-dev@ws.apache.org by Alexey Loubyansky <al...@jboss.org> on 2003/12/17 12:00:35 UTC

IoC document factory

While I am getting acquainted with the codebase I would like to know 
your critiques on my ideas.

I would like to start with the user part of unmarshalling. There are two 
required things: class hierarhy that represents the content (document) 
and the factory which will create and populate the objects (nodes of the 
document) with data from an XML source.

The factory is based on Inversion of Control and is called by the engine 
when a new element is started, finished, etc.
The following methods are required for each factory:
/**
  * This method is called by the parser and should return an object that
  * represents the document object.
  */
public Object startDocument()

/**
  * This method is called by the parser when the parsing is done.
  * The metadata parameter is the object that was returned by the
  * startDocument()
  */
public void endDocument(Object document)

Other methods are optional and will be discovered by introspection.

A set of newChild() methods.
This method is called by the parser when the parsing of a new element is 
started. Each newChild() method should have three parameters:
1. the parent object for this new child. For the root element the 
document (or root) object returned by the startDocument() is passed as 
the parent object.
2. the second one is the namespace URI of the element.
3. the third one is the local name of the element.

Each newChild() method returns either an instance of the object that 
represents the element (in this case, the child is accepted, i.e. should 
be represented in the document object tree) or null if this element 
should be ignored, i.e. not be represented in the content.

A set of setValue() methods.
This method is called whenever a new simple element (i.e. an element 
that does not contain nested elements) with text value was read.
The method has three parameters:
1. the object which was returned by the newChild() method earlier, which 
is the parent for the value read;
2. the namespace URI of the child element;
3. the local name of the child element;
4. the value of the child element.

A set of addChild() methods.
This method is called by the parser when the parsing of the child object 
is done. The method has the following parameters:
1. the parent object;
2. the child object (returned by the newChild() earlier).

When addChild() is called the child object is read, can be validated and 
added to (ne registered with) the parent.

I am attaching a simple factory. It was written for this example:
http://www.xml.com/pub/a/2000/11/29/schemas/part1.html

Note, the default object model and the factory can be generated 
(proposed) or supplied by an application developer. You can build an 
populate really exotic hierarchies and have full control over the process.

What do you think?

Re: IoC document factory

Posted by Alexey Loubyansky <al...@jboss.org>.
Jochen Wiedmann wrote:
> Alexey Loubyansky wrote:
> 
>> But this contradicts the current JAXB API. A legal workaround could be:
>> unmarshaller.setProperty("jaxme.objectfactory", objectFactory);
>> MyDocument document = unmarshaller.unmarshal(source);
> 
> Makes sense. I would still suggest to read the default from the config 
> file,
> because
> 
> - one can use a generic instantiation code, otherwise the name of the
>   default factory needs to be compiled in somewhere
> - one can replace the factory without changing the code

Ok

> Please note, that you have just implicitly voted for a factory with
> schema scope, because the property you have choosen is not element
> specific. I must admit, that I am not too keen with this. However,
> we might take that as a start.

Ok

>> Yes, I see. But are you allowed to put jaxme specific configuration in 
>> jaxb.properties? I am not saying Configuration.xml is bad, just 
>> thiking how it would be easier for me as the user. Finally, it's only 
>> one config file which is required anyway.
> 
> As these things are JaxMe specific, I would definitely vote for putting 
> such
> things into the JaxMe specific configuration. The jaxb.properties are read
> by JAXBContext (which class is *not* JaxMe specific, but can be replaced
> by the same class in JAXB RI). The Configuration.xml file is read from
> JAXBContextImpl. Using information from jaxb.properties in JAXBContextImpl
> will only complicate things.

I wanted to find something in the spec in this regard. But the only 
reference to jaxb.properties is that it should contain 
javax.xml.bind.context.factory.

I kind of got used to the idea that a config file contains some spec 
defined configuration and some vendor specific. In this case, all 
implementations are required to understand the spec related options and 
skip unrecognized ones, i.e. other vendors' options.
The advantage of this approach is that it standardizes the configuration 
across different implementations and everything is in one place. As for 
me, it is simpler from the user's point of view, especially, when the 
config is not huge.
Just my opinion.

Thanks,

Alexey


---------------------------------------------------------------------
To unsubscribe, e-mail: jaxme-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: jaxme-dev-help@ws.apache.org


Re: IoC document factory

Posted by Jochen Wiedmann <jo...@ispsoft.de>.
Alexey Loubyansky wrote:

> But this contradicts the current JAXB API. A legal workaround could be:
> unmarshaller.setProperty("jaxme.objectfactory", objectFactory);
> MyDocument document = unmarshaller.unmarshal(source);

Makes sense. I would still suggest to read the default from the config file,
because

- one can use a generic instantiation code, otherwise the name of the
   default factory needs to be compiled in somewhere
- one can replace the factory without changing the code

Please note, that you have just implicitly voted for a factory with
schema scope, because the property you have choosen is not element
specific. I must admit, that I am not too keen with this. However,
we might take that as a start.


> At the moment, for this approach, I see no other way but generate the 
> object factory with the schema class hierarchy (and configuration file?) 
> and add a configuration option for the unmarshaller in Configuration.xml 
> or jaxb.properties to use this object factory.

+1


> BTW, do you generate the config file also? AFAICS, it should not be hard 
> to do.

Yes, of course. See the generateConfigFile method in JAXBSchemaSGImpl.


> But I would still like to be able to override this option 
> programmatically like it is above or in some other way.
> 
> What do you think?

+1


> Yes, I see. But are you allowed to put jaxme specific configuration in 
> jaxb.properties? I am not saying Configuration.xml is bad, just thiking 
> how it would be easier for me as the user. Finally, it's only one config 
> file which is required anyway.

As these things are JaxMe specific, I would definitely vote for putting such
things into the JaxMe specific configuration. The jaxb.properties are read
by JAXBContext (which class is *not* JaxMe specific, but can be replaced
by the same class in JAXB RI). The Configuration.xml file is read from
JAXBContextImpl. Using information from jaxb.properties in JAXBContextImpl
will only complicate things.


Jochen


---------------------------------------------------------------------
To unsubscribe, e-mail: jaxme-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: jaxme-dev-help@ws.apache.org


Re: IoC document factory

Posted by Alexey Loubyansky <al...@jboss.org>.
Hello Jochen,

Jochen Wiedmann wrote:
>> I thought, that the configuration of the factory is done with the 
>> methods like newChild(), addChild(), setValue(), etc. Isn't it enough? 
>> I may miss something.
> 
> There are questions left. For example: How does the user supply his own
> factory? How does the default implementation work?

Ideally, as the user, I would like to see it like:
MyDocumentObjectFactory objectFactory = ... // create/get the instance
MyDocument doc = unmarshaller.unmarshal(source, objectFactory);

But this contradicts the current JAXB API. A legal workaround could be:
unmarshaller.setProperty("jaxme.objectfactory", objectFactory);
MyDocument document = unmarshaller.unmarshal(source);

What about defaults?

At the moment, for this approach, I see no other way but generate the 
object factory with the schema class hierarchy (and configuration file?) 
and add a configuration option for the unmarshaller in Configuration.xml 
or jaxb.properties to use this object factory.
BTW, do you generate the config file also? AFAICS, it should not be hard 
to do.
But I would still like to be able to override this option 
programmatically like it is above or in some other way.

What do you think?

> The current implementation is JAXBContextImpl, which is configured through
> Configuration.xml. In other words, A user is able to replace the classes
> generated by JaxMe by simply editing the config file. (This is a task
> well suited for Ant and its copy task.)

Yes, I see. But are you allowed to put jaxme specific configuration in 
jaxb.properties? I am not saying Configuration.xml is bad, just thiking 
how it would be easier for me as the user. Finally, it's only one config 
file which is required anyway.

>> It will work. But what is the reason to make a rule of it? You seem to 
>> support the idea that the factory is provided by the user. So, why not 
>> let the user decide whether to make it singleton? This is important.
> 
> 
> The question is again: What will the default implementation do? How much
> instances will it use? My answer is: Let it use a single. In particular: 
> Design the factory interface in a way that allows to create all factories
> when the application comes up.

As for the default, it's fine.

>> As for me, the startDocument() method is required. It returns the root 
>> element (creating with new or... not) which will be then passed in as 
>> the parameter to newChild, addChild and other methods. It does not 
>> contradict sigletons.
> 
> Agreed. I misunderstood the methods name. I would suggest createRoot()
> or something similar.

Agree. Some other method names should also be reviewed.

Thanks,

Alexey


---------------------------------------------------------------------
To unsubscribe, e-mail: jaxme-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: jaxme-dev-help@ws.apache.org


Re: IoC document factory

Posted by Jochen Wiedmann <jo...@ispsoft.de>.
Alexey Loubyansky wrote:

> I thought, that the configuration of the factory is done with the 
> methods like newChild(), addChild(), setValue(), etc. Isn't it enough? I 
> may miss something.

There are questions left. For example: How does the user supply his own
factory? How does the default implementation work?

The current implementation is JAXBContextImpl, which is configured through
Configuration.xml. In other words, A user is able to replace the classes
generated by JaxMe by simply editing the config file. (This is a task
well suited for Ant and its copy task.)


> It will work. But what is the reason to make a rule of it? You seem to 
> support the idea that the factory is provided by the user. So, why not 
> let the user decide whether to make it singleton? This is important.

The question is again: What will the default implementation do? How much
instances will it use? My answer is: Let it use a single. In particular: 
Design the factory interface in a way that allows to create all factories
when the application comes up.


> What is the difference between the first (All) and the last (Any)? Does 
> 'Any' mean a factory per element?
> In my case, there is one factory per schema/document. I think, it is 'All'.

I expressed myself wrong. Sorry! Suggest the following XML documents and
assume they are declared as top level elements in a schema:

                 <a b="c">
                   <d>
                     <e/>
                   </d>
                 </a>

                 <f>
                   <g x="y"/>
                 </f>

The question is: How many object factories are suitable for this schema?
We can have

- one creating all objects
- two factories (one creating the elements a, d, e and the attribute b and
   one factory creating f, g, and x)
- four factories (one creating a, and b, one creating d and e, one
   creating f, and one creating g, and x)

Just to give a rough idea what I mean when talking about a factories scope.


> I am a newbie here and not aware of portability issues. So, please, just 
> let me know and correct me.

In theory it should be possible to take an application running with
the JAXB RI, exchange the Ant task in the build script and have a
running JaxMe application.


> As for me, the startDocument() method is required. It returns the root 
> element (creating with new or... not) which will be then passed in as 
> the parameter to newChild, addChild and other methods. It does not 
> contradict sigletons.

Agreed. I misunderstood the methods name. I would suggest createRoot()
or something similar.


> In my understanding singleton means there can only be one instance of 
> the class in VM. Do you imply that singleton is also a stateless thread 
> safe object?

I misuse the term singleton. You are right, what I actually want is a
stateless object that may be shared in multiple threads.


Jochen

---------------------------------------------------------------------
To unsubscribe, e-mail: jaxme-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: jaxme-dev-help@ws.apache.org


Re: IoC document factory

Posted by Alexey Loubyansky <al...@jboss.org>.
Jochen Wiedmann wrote:
> 
> Hi, Alexey,
> 
> took me some time to reply, as your mail also took some time to read. :-)

I appreciate the quality first of all and it takes time ;)

> 
> 1.) I appreciate the idea of an object factory, if
> 
>       * it is configurable, thus exchangeable by the user

I thought, that the configuration of the factory is done with the 
methods like newChild(), addChild(), setValue(), etc. Isn't it enough? I 
may miss something.

>       * it is implemented as a singleton (not necessarily with
>         a private constructor, but in a way that allows to restrict
>         the number of instances)

It will work. But what is the reason to make a rule of it? You seem to 
support the idea that the factory is provided by the user. So, why not 
let the user decide whether to make it singleton? This is important.

> 
>     The question arises: Which scope should the object factory have? I
>     see three possible answers:
> 
>       * All objects of the schema; in that case the current ObjectFactory
>         (as specified by JAXB) may be used, with JaxMe specific
>         extensions. In other words, we would need a possibility to
>         configure the ObjectFactory (triviality, can be done in
>         Configuration.xml)
>       * One top level element; in that case the JaxMe implementation of the
>         JAXB ObjectFactory needs to be configurable to exchange the
>         implementation. Again, this can be done in Configuration.xml.
>       * Any element, possibly even any group; this complicates the
>         configuration and the implementation. On the other
>         hand it definitely might helk to resolve ambiguities like
>         duplicate names and the like (do not underestimate that!)

What is the difference between the first (All) and the last (Any)? Does 
'Any' mean a factory per element?
In my case, there is one factory per schema/document. I think, it is 'All'.

> 
>     Note, that we are discussing issues here, that may cause portability
>     problems.

I am a newbie here and not aware of portability issues. So, please, just 
let me know and correct me.

> For example, if we should not force the user to use an
>     object factory, as he may choose the implementation class (at least
>     the JAXB specification allows him to do so, with good reasons)

If the user uses a generator then the factory could be generated with 
the document class hierarchy. In this case, the user might not care of 
the factory at all. But the tool can still use it.
So, I would rephrase your sentence as "we should not force the user to 
use AN OBJECT FACTORY APPROACH". That is absolutely fine with me.

> 
> 2.) I question the value of methods like startDocument() and
>     endDocument().

As for me, the startDocument() method is required. It returns the root 
element (creating with new or... not) which will be then passed in as 
the parameter to newChild, addChild and other methods. It does not 
contradict sigletons.

> They only make sense, if the factory has some state.
>     It should not, IMO, because that forbids to use singletons. In
>     other words, it blows up the number of objects.

In my understanding singleton means there can only be one instance of 
the class in VM. Do you imply that singleton is also a stateless thread 
safe object?
In fact, I don't see how start/end methods forbid this. Suppose, 
startDocument alsways returns a new object which then is passed as the 
parameter to the endDocument method.

> 
>     Note, that we already have a stateful object in the unmarshalling
>     process: It is the Handler (one per complex type, be it named or
>     anonymous type) and it already has methods like startDocument()
>     and endDocument() because SAX specifies them.

Yes.

> 
>     I would suggest to leave the SAX handler as a controller, like it
>     is now.
> 
> 3.) Please: In no case use introspection as part of the unmarshalling
>     or marshalling process! It slows down and it moves control from
>     compile time to run time.

Object factory methods are called by the framework using reflection. So, 
at some time, we have to discover the methods of the object factory. It 
can and, probably, should be done only once before parsing but there is 
no way to avoid introspection.

> 
>     Whoever wants to use introspection, may use Betwixt, because it

Ok, thanks.

>     does an excellent job in that area. Introspection is valid as a
>     part of the generation stage. We can also discuss whether it makes
>     sense for handling wildcard elements and/or attributes.
> 
> 
>> A set of newChild() methods.
>  > A set of setValue() methods.
> 
> 4.) Makes quite some sense in the object factory. Note, that one needs
>     in fact two versions of setValue, one for attributes and one for
>     simple elements. Perhaps even a third version for the contents of
>     an element with simple content and attributes (in that case
>     without namespace and local name).

Yes, I just skipped the attributes for now. Maybe, it makes sense to 
pass attributes in the newChild method to avoid so many setValue 
methods? I would like to keep it simple.

>> Note, the default object model and the factory can be generated 
>> (proposed) or supplied by an application developer. You can build an 
>> populate really exotic hierarchies and have full control over the 
>> process.
> 
> 
> 5.) I strongly support the idea of supplying an object factory by the
>     user.

Ok for me.

> I disagree in the case of the controller, at least in the
>     current stage.

Since you liked the object factory idea, I guess, you misunderstood my 
'controll'.
Let me clarify. I meant controll in building and populating the object 
model. It can be really exotic and I would like to be able, for example, 
to add a child as an array or list element, or put it in the Map with 
some key, or even do it all together if I keep chidren in a list and a 
map at the same time.
I am not sure this is same as you meant by the controller.

Thanks,

Alexey


---------------------------------------------------------------------
To unsubscribe, e-mail: jaxme-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: jaxme-dev-help@ws.apache.org


Re: IoC document factory

Posted by Jochen Wiedmann <jo...@ispsoft.de>.
Hi, Alexey,

took me some time to reply, as your mail also took some time to read. :-)

1.) I appreciate the idea of an object factory, if

       * it is configurable, thus exchangeable by the user
       * it is implemented as a singleton (not necessarily with
         a private constructor, but in a way that allows to restrict
         the number of instances)

     The question arises: Which scope should the object factory have? I
     see three possible answers:

       * All objects of the schema; in that case the current ObjectFactory
         (as specified by JAXB) may be used, with JaxMe specific
         extensions. In other words, we would need a possibility to
         configure the ObjectFactory (triviality, can be done in
         Configuration.xml)
       * One top level element; in that case the JaxMe implementation of the
         JAXB ObjectFactory needs to be configurable to exchange the
         implementation. Again, this can be done in Configuration.xml.
       * Any element, possibly even any group; this complicates the
         configuration and the implementation. On the other
         hand it definitely might helk to resolve ambiguities like
         duplicate names and the like (do not underestimate that!)

     Note, that we are discussing issues here, that may cause portability
     problems. For example, if we should not force the user to use an
     object factory, as he may choose the implementation class (at least
     the JAXB specification allows him to do so, with good reasons)

2.) I question the value of methods like startDocument() and
     endDocument(). They only make sense, if the factory has some state.
     It should not, IMO, because that forbids to use singletons. In
     other words, it blows up the number of objects.

     Note, that we already have a stateful object in the unmarshalling
     process: It is the Handler (one per complex type, be it named or
     anonymous type) and it already has methods like startDocument()
     and endDocument() because SAX specifies them.

     I would suggest to leave the SAX handler as a controller, like it
     is now.

3.) Please: In no case use introspection as part of the unmarshalling
     or marshalling process! It slows down and it moves control from
     compile time to run time.

     Whoever wants to use introspection, may use Betwixt, because it
     does an excellent job in that area. Introspection is valid as a
     part of the generation stage. We can also discuss whether it makes
     sense for handling wildcard elements and/or attributes.


> A set of newChild() methods.
...
 > A set of setValue() methods.

4.) Makes quite some sense in the object factory. Note, that one needs
     in fact two versions of setValue, one for attributes and one for
     simple elements. Perhaps even a third version for the contents of
     an element with simple content and attributes (in that case
     without namespace and local name).


> Note, the default object model and the factory can be generated 
> (proposed) or supplied by an application developer. You can build an 
> populate really exotic hierarchies and have full control over the process.

5.) I strongly support the idea of supplying an object factory by the
     user. I disagree in the case of the controller, at least in the
     current stage.

     The current version of JaxMe is in fact my third approach of a
     Java/XML binding framework. The first version has been quite
     limited. However, it was quite easy to give control to the user.
     The second is what we now know as JaxMe 1. It was not so limited,
     but it became harder to control it. JaxMe 2 is even more complex.
     To implement all requirements of XML Schema it needs to become
     much more complex than it is now.

     If we require now, that the user has control, we restrict ourselves,
     because we may not change the internals so easily. If we arive at a
     point where we have done the job (which may be validated using the
     JAXB TCK), then we may return to this idea, refactor the stuff and
     return control to the user. That makes sense.



Jochen


---------------------------------------------------------------------
To unsubscribe, e-mail: jaxme-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: jaxme-dev-help@ws.apache.org