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]