Hi Peter

(Comments inline)

On 14.04.2002 04:15:25 Peter B. West wrote:
> Joerg,
> 
> Thanks, it does answer my questions, and raises a few others.  I'm 
> heartened by this, because what you have described is the inappropriate 
> use of global data in a multi-threaded context.  I'm interested because 
> I like statics.  They are smaller and faster; what's not to like? 
>  Before continuing with them, though, I need to make sure that I 
> understand the problems.

I agree with you that statics are convenient. I used to work with them a
lot, but stopped in most cases since we started to use Avalon in our
applications. They were too much of a stone in the way of using the same
package/component multiple times in different ways.

For example we had a static class for JNDI access. That's nice as long
as you're accessing only one JNDI server. Today we've got an
Avalon-style component named JNDIProvider that's configured over an XML
file (using ExcaliburComponentManager). All we have to do to access a
second JNDI server at the same time is to provide another JNDIProvider
under a different name and use that name in the configuration of the
JNDI-consuming component.

> The scenario you describe is a doomed attempt to globalise local data. 
>  However, there are times when some initialization of truly global data 
> is required, yet it cannot be accomplished with static{} blocks.  What's 
> needed is a one-time initialization method.  This can be synchronized. 
>  Protect the initialization method or some initialization object, and 
> set a flag within the method to declare that the job is done.  Test this 
> on entry, after synchronization.  Because none of the processes which 
> require the data will attempt access until after init, access itself 
> does not need to be synchronized.  (I'm assuming here that all statics 
> are global relative to the JVM.)

As far as I know, you can't assume that, because the statics are global
within the context of a ClassLoader and not the JVM. Normally though,
you have only a simple ClassLoader hierarchy. In that case your
assumption is right. But it isn't as soon as some complex classloading
is done (as in EJB servers, web containers, Avalon Phoenix etc). In that
regard, Arnd could (probably!) have run two differently configured FOPs
in one VM, but not without major headaches, I think. That's why I
personally would like to get rid of all unneccessary statics that could
be in the way of using FOP in a multithreaded and multi-configuration
environment.

Configuration IMO should be done directly on the component and not in a
global way. You gain a lot of flexibility.

For illustration, I've just done a quick search over the Avalon
subprojects Framework, Excalibur and Phoenix to see how many non-final static
variables are used. I've found a few, but I'm convinced that most should
also have been marked final because they are actually constants. Most
other instances are used in a context of wrapping other non-Avalon parts
that make use of statics. What I want to say is this: I believe that
it's possible (and worthwhile) to remove the statics where FOP
configuration is concerned. A possible way to do this is using the
facilities that Avalon provides. The Driver class (or something similar)
will be a container for all FOP-related components/classes and will be
the central point of configuration. The container will propagate the
configuration down to it children (following the Inversion of Control
pattern). That way we can have something similar to the JAXP approach of
configuration (as Joerg proposes).

> It seems to me, of what I have heard so far, that there is no problem 
> with statics _per se_.  If they are used with an awareness of the 
> possibility of multi-threading, they should present no special 
> difficulties.  I have heard it said, though, that statics are forbidden 
> in EJB environments.  Is this true?  If so, what are the special 
> constraints that apply to EJBs?

See Arved's comment.

> Regarding configuration in FOP, it is interesting to note that there are 
> two different config hierarchies depending on whether the environment is 
> uniform, as, e.g., in a single thread, or diverse, as in the example 
> Arnd offered.  (That is, a separate process constructs stylesheet 
> information and other variables into an instance-specific storage 
> location, and invokes a fop thread with a reference to that location.)
> 
> In the first case, the config hierarchy is:
> 
> system config
> user config
> command line
> 
> despite the fact that the user config file may be specified on the 
> command line.  Other data from the command line will override 
> assignments in the user config (else why specify them?)
> 
> In the second scenario, the most instance-specific data is in the user 
> config file (if that is being used to pass the instance data) or in some 
> other instance-specific config source.  So the hierarchy looks like:
> 
> system config
> command line
> user config
> 
> or
> 
> system config
> user config
> command line
> instance config
> 
> I like the second idea better.

I'm not sure what difference you see between command line and instance
config.

I'd not stick too much to the command line anyway when we also use FOP
embedded in Cocoon or other multithreaded environments. I'd also
separate configuration (fonts, renderer options etc.) from processing
parameters (XML/XSLT/XSL:FO-files, baseDir/baseURL, target format etc.).
That's because FOP provides a service (convert XSL:FO to some other
format). This service has a configuration (describing its components and
their individual configuration). Once the FOP service is instantiated
you can call the service multiple times, each time with different
processing parameters. For the command line that simply means the
service is instantiated and is called only once. The separation of
system and user configuration is another issue where I'm not sure
whether this will stay in the future and whether the meaning of the two
will change with the use of Avalon.

There's still one question: Do we want to change the way configuration
is done in the maintenance branch? I think not, because it might be a
major task. I mean, I'm in the same boat as Arnd but I can live with the
work-arounds for now. Other opinions?

> Not knowing a great deal about JVMs and class loaders, I'm curious to 
> know how dynamic data can be introduced into threads started within a 
> pre-existing JVM.  One solution of Arnd's problem would seem to be to 
> control the process of setting up the FOP thread configuration 
> subdirectories from within the JVM, and allow for new FOP objects to be 
> initialised with this information.  That is not a general solution ot 
> the problem though.  How is it usually done?

As long as FOP uses static configuration you end up with classloader
magic which is not so nice. The only solution I see is to associate
configuration data with a service instance (the FOP container (today: Driver.java),
the black box service which controls its children (tree builder, image
reader, layout managers, renderers etc.). That's also how it is done in
JAXP.

I suggest you read "Developing with Avalon" to get an idea how Avalon
works. You can find a HTML and PDF version at
http://jakarta.apache.org/avalon.


Cheers,
Jeremias Märki

mailto:[EMAIL PROTECTED]

OUTLINE AG
Postfach 3954 - Rhynauerstr. 15 - 6002 Luzern
Fon +41 41 317 2020 - Fax +41 41 317 2029
Internet http://www.outline.ch


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]

Reply via email to