We were looking at caching a Templates object for reuse with XSLTC but were a little confused in that it is the newTransformer that does the compilation. The class compiled (the translet) seems to be a Transformer. So caching the Template object is not much use.
One critical aspect of Templates is that they are thread safe. I presume Translets are not ?
Is it safe as a workaround to :
- after calling newTransformer for the first time cast the result back to AbstractTranslet and cache the result of getTransletName() and the result of calling Class.forName(transletName);
- then while the cache is not dirty instead of calling newTransformer again do
- Class transletClass = <read Class from cache (or do the Class.forName again)>
- translet = (Translet)transletClass.newInstance();
- ((AbstractTranslet)translet).setTransletName(<read name from cache>);
Or is it likely that the compilation will move soon to newTemplates with the TransletTemplates class retaining the Class object and the class name and TransletTemplates#newTransformer change to doing a newInstance on the stored Class and then setting the translet name ? All the code exists for this, it would just need to be re-organised a little.
Two new instance variables (transletName, transletClass) could be added to store the Classs and its name. The first half of TransletTemplates#newTransformer() could move to the constructor with the only change being that transletName would no longer be local it would be one of the instance variables.
The second half of that method would stay where it is with the changes that it also would use this.tansletName and this.transletClass rather than doing a classForName.
TransformerFactoryInpl#newTransformer(Source source) would then be something like
Templates tmpl=newTemplates( source );
if( tmpl==null ) return null;
return tmpl.newTransformer();
Does this make sense ?
Regards,
Padraig
Gary L Peskin wrote:
[EMAIL PROTECTED]">Morten --
I may be missing something here and I'm sure Scott will jump in but here
is my understanding of things. I don't really think that TRaX has "...
loads of crap ... that most users will never bother even looking at" but
I could be wrong there too.
Basically,
Templates <==> Translet class
Transfomer <==> Translet object/instance
You say that "the current code wraps the translet (or actually the
translet base class) inside a transformer object." In TRaX terms, this
should really be in a Templates object. Once inside the Templates
object, the user can cache this to his or her content. Switching to a
TRAX-conformant XSLTC will allow the user to use the caching strategy
already in place.
Now, when a transform is desired, the user creates a Transformer from
the Templates object by calling Templates.newTransformer(). This is
just creating a newInstance() of the Translet embodied in the Templates
object. This should be a lightweight operation, not requiring a
recompilation like the current Transformer generation but just a new
instance of the translet.
I think that part of the confusion stems from the fact that there are
two ways to get a transformer in TRaX:
TransformerFactory.newTransformer(Source)
-and-
TransformerFactory.newTemplates(Source) -followed by-
Templates.newTransformer()
The first method is good for one-shot prototypes or other applications
where there is no need to maintain the translet -class- for multiple
invocations. The second method is used for industrial strength
applications where we compile once and then execute instances lots of
times.
It sounds like you're currently doing your compiling in
Templates.newTransformer() but that is not where it should be
happening. It should be happening in
TransformerFactor.newTemplates(Source).
If you already realized this, then I've completely misunderstood
everyone's point and I'll just go away. Otherwise, please come back
with any questions.
Thanks,
Gary
Morten Jorgensen wrote:[EMAIL PROTECTED] wrote:Morten Jorgensen <[EMAIL PROTECTED]> wrote:and we don't want to compile such classes more often
than we have to, and this is the reason why we want
cache translets.My position is that the XSLT processor should not be doing caching.
I have said this many times and I will continue to say it.Why would anyone bother to use compiled stylesheets if they have to
be compiled for every transformation (or sequence of transformations)?
There is not reason at all to use XSLTC if translets are not pre-
compiled and stored. XSLTC spends ca. 4 times as long to compile a
translet as any other XSLT processor uses on a transformation. If our
JAXP implementation forces a compilation for each time a translet is
loaded we would make XSLTC the slowest XSLT processor on the market.
If XSLTC is made the slowest JAXP compliant processor there is, then
I don't think many people will bother use it - except for those that
are still using its native APIs - and there would be no reason to
add JAXP support at all.Here's how it should work in my opinion:
org.apache.xalan.xsltc.compiler.XSLTC should implement javax.xml.transform.
TransformerFactory.
org.apache.xalan.xsltc.compiler.XSLTC#newTemplates(Source source) should
compile the source object into a Translets, and create a small wrapper
class, org.apache.xalan.xslt.TemplatesImpl that contains the Class object,
or perhaps just the class name (or, perhaps you get fancier than that and
it holds the actual bytecodes... dunno).There are still loads of people that prefer to use the native APIs of XSLTC.
Many of these users stick to XSLTC because of its small footprint, and not
so much for performance reasons. I would like to separate the JAXP/TrAX
wrappers from the existing XSLTC source tree (leaving the existing code
untouched - for now) and putting all TrAX wrappers in a separate directory:
a) org.apache.xalan.xsltc.runtime - existing code
b) org.apache.xalan.xsltc.dom - internal DOM
c) org.apache.xalan.xsltc.trax - TrAX wrappers/etc.
There is loads of crap in TrAX that most users will never bother even looking
at. I don't want to force this stuff upon those users that are more than
happy to use just a) and b) above (this is the case for those that are using
XSLTC in applets). I know that the current code wraps the translet (or actually
the translet base class) inside a transformer object. Nowmatter how fancy this
looks on a design diagram it is not desireably/practical for many users.Everytime the caller calls TransformerFactory#newTemplates(Source source),
org.apache.xalan.xsltc.compiler.XSLTC#newTemplates(Source source) will
compile a new Translet, period. Caching that object is the responsibility
of the caller, which can use whatever mechanisms are suitible.
org.apache.xalan.xslt.TemplatesImpl#newTransformer() should simply call
Class#newInstance() on the the contained Translet class object.
This seems really simple to me. Applications that are already caching
Templates objects then start caching XSLTC translets automatically, with
the same mechanism.Sure, users can cache Template instances as much as they want to nomatter
what is wrapped in inside the Template. But, this means that the stylesheet
is compiled every time the user wants to instanciate a translet _object_.
This, again, undermines the whole idea of compiling stylesheets.
Most of the software I use is open-source and is distributed as source code.
I compile this software once, store it as binaries and load it into memory
when I need it. I do not compile it every time I run it and then keep it
memory for as long as I can. This is mainly for two reasons:
a) I don't want to wait for it to compile every time I load it
b) I do not have enough memory on my PC to keep it in memory at all times
This holds for translets too. A web server that uses XSLTC would proably
not be able to keep Template/Transformer objects for all stylesheets in
memory at all times. Neither would it be preferrable to compile stylesheets
every time a new Transformer/Template object is instanciated.Our main concern is where to store the translets (a simple Java
property file pointing to a directory may do)Does the class have to be put on disk? (A question... I simply don't
know). If it does, I guess I would use a system property to indicate the
storage directory.Yes, we absolutely, definately need to be able to store translet
_classes_ somewhere. A simple property could be used. If the property we
use is set, then translets can be cached in the directory (or whatever)
the property points to, otherwise caching is turned off.and how to make sure that a translet in the cache is still validThis is one of the reasons you really shouldn't muck with caching.
Whatever you do will cause somebody problems. Put this responsibility at
the application level where it belongs.Template/Transformer caching definately belongs at the application level.
How these objects are created is our responsibility. And we want to create
them as efficiently as we can.
Morten
