commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Arnaud Masson <arnaud.mas...@kikamedical.com>
Subject Re: [Jelly] nested compileScript() with import ?
Date Tue, 07 Dec 2004 08:33:03 GMT
Hans Gilde wrote:

>Maybe it's getLastModified instead of getDate?
>
>  
>
yes, it works much better!

>You probably know, but there's another performance characteristic of my
>solution: the Servlet threads only contend for a lock during the time it
>takes to look the Script up from the Map. With yours, the threads have a
>much larger window for contention. This would only make a difference if your
>application will run many instances in many threads.
>
>  
>
I agree.
(in my case the number of concurrent connections is small)

>What about an application variable "flushJellyCache"? At the beginning of
>the Servlet, check for that variable. If it's true, lock the application,
>remove all from the Map, set to false. Now you can flush the cache by hand
>from the web interface or a management client.
>
>  
>
Now that I can get the date of the script files, I can implement an 
automatic flushing and manage the global cache that you describe,
so my per-session cache solution isn't useful anymore.
That's what occurs in JSP, when you edit a .jsp page, it is recompiled 
transparently.

Thanks.
With your help, there is now no advantage left for JSP compared to jelly.

>Hans
>
>-----Original Message-----
>From: Arnaud Masson [mailto:arnaud.masson@kikamedical.com] 
>Sent: Monday, December 06, 2004 12:11 PM
>To: Jakarta Commons Users List
>Subject: Re: [Jelly] nested compileScript() with import ?
>
>Hans Gilde wrote:
>
>  
>
>>Arnaud,
>>
>>You're right about how JSP works; maybe you could file an issue about this
>>in Jelly's jira? This seems like something that many web users would want.
>>
>> 
>>
>>    
>>
>done (sorry for the double post #170/171, the server wasn't responding)
>
>  
>
>>Sorry to introduce problems but...
>>
>>To get the benefit of your solution, you will need to reuse the cache
>>between Servlet invocations. The basic Jelly Servlet does not reuse the
>>JellyContext between invocations. Here's the pain: the context isn't
>>entirely thread safe (actually, the parser isn't thread safe and the
>>    
>>
>context
>  
>
>>uses a single parser).
>>
>>Here's what you can do:
>>
>>Set the HashMap into the context before invoking the script. If inherit is
>>true (by default), the Map will be accessible throughout your entire
>>    
>>
>script.
>  
>
>>Now that your Servlet has a handle on the HashMap, you can keep it in an
>>instance variable (must be a thread safe HashMap) or as an application
>>variable or whatever.
>>
>> 
>>
>>    
>>
>Currently I put the JellyContext (including the script cache) in the web 
>session.
>When I use this JellyContext , I do a synchronized(myContext) {...} to 
>avoid the threading problem.
>Of course the cache isn't shared across session.
>
>Your solution is better but the per-session solution has one advantage.
>You can easily purge the cache when you open a new session, which is 
>useful when you modify the jelly scripts.
>I have tried to use URLConnection.getDate() to discard the cache,
>but it doesn't work on the jndi URL provided by tomcat with 
>ServletContext.getResource(), it always returns 0.
>Any idea how I can manage cache update ?
>
>  
>
>>-----Original Message-----
>>From: Arnaud Masson [mailto:arnaud.masson@kikamedical.com] 
>>Sent: Monday, December 06, 2004 4:06 AM
>>To: Jakarta Commons Users List
>>Subject: Re: [Jelly] nested compileScript() with import ?
>>
>>Hans Gilde wrote:
>>
>> 
>>
>>    
>>
>>>Ok, it sounds reasonable to want those caching conditions. But for my own
>>>curiosity, why do you want them? Are you in a tight memory situation or is
>>>it a perfectionist thing?
>>>
>>>
>>>
>>>   
>>>
>>>      
>>>
>>It's for speed, especially for Script.run().
>>I must run many small scripts to build page, so I would like to minimize 
>>IO and XML parsing.
>>The outputs of the scripts are assembled in a big DOM,
>>under the control of a java loop which also makes some modifications to 
>>the DOM.
>>(I use a custom ContentHandler so that jelly output is directly added in 
>>the document without parsing.)
>>
>>I think that in a classic JSP, all included pages are compiled when the 
>>main jsp  is compiled,
>>so there is no performance penalty there. I would like the same thing in 
>>jelly.
>>
>> 
>>
>>    
>>
>>>What's wrong with using JellyContext variables? It's pretty much what
>>>they're there for.
>>>
>>>
>>>
>>>   
>>>
>>>      
>>>
>>I had the idea that the cached scripts were technical details and should 
>>not be at the same level as user variables.
>>This time, it's probably a "perfectionist thing" ! :-)
>>
>> 
>>
>>    
>>
>>>You can think of a JellyContext as a scope. At each level of XML tag, you
>>>get a new JellyContext (a new scope). Export says "when a variable is set
>>>into the current scope, should I automatically put it into the scope
>>>   
>>>
>>>      
>>>
>>above"?
>> 
>>
>>    
>>
>>>Inherit says "when creating a new scope, should I give it all the
>>>      
>>>
>variables
>  
>
>>>   
>>>
>>>      
>>>
>>>from the current scope"?
>> 
>>
>>    
>>
>>>If a Tag wants to set a variable in a context (scope) that's higher up in
>>>the tree, there are two choices: use export=true or find the parent
>>>      
>>>
>context
>  
>
>>>(while ((parent = getParent()) != null)).
>>>
>>>To find a variable that's been set into a context above yours, either use
>>>inherit=true or findVariable.
>>>
>>>I'd suggest this solution:
>>>
>>>Have your Tag find the top level context (while ((parent = getParent()) !=
>>>null)). Use a single variable name in this context, say
>>>   
>>>
>>>      
>>>
>>my_imported_scripts.
>> 
>>
>>    
>>
>>>That variable will be a single HashMap from uri to parsed Script instance.
>>>
>>>
>>>   
>>>
>>>      
>>>
>>Ok, I'm going to try this.
>>
>> 
>>
>>    
>>
>>>As you saw, compilable tags are sort of compiled, but they don't get a
>>>context or their attributes at that point. The problem with compilable
>>>      
>>>
>tags
>  
>
>>>(I don't recommend using them) is that they're only compiled with respect
>>>   
>>>
>>>      
>>>
>>to
>> 
>>
>>    
>>
>>>the thread that compiles them. If you run the same Script in a different
>>>thread, those compiled tags won't be there. This is not true for a Script.
>>>Once a Script is compiled, it stays compiled no matter where you use it.
>>>
>>>
>>>
>>>   
>>>
>>>      
>>>
>>I don't think I need the advanced Script based solution for now, the 
>>cache map must be sufficient for me.
>>
>>Thanks for your help.
>>
>> 
>>
>>    
>>
>>>Hans
>>>
>>>-----Original Message-----
>>>From: Arnaud Masson [mailto:arnaud.masson@kikamedical.com] 
>>>Sent: Sunday, December 05, 2004 5:06 PM
>>>To: Jakarta Commons Users List
>>>Subject: Re: [Jelly] nested compileScript() with import ?
>>>
>>>Yes,  I have copied the import tag and added the cache to the new tag.
>>>It works fine, but I would like to reuse compiled scripts
>>>- if several container scripts include the same sub script
>>>- if a container script include the same sub script several times
>>>
>>>To do that, I currently use the JellyContext to cache compiled scripts 
>>>with a call to setVariable(),
>>>using a variable name based on the script uri... it works, but it's not 
>>>really clean.
>>>
>>>Maybe a better way would be to override the compileScript() methods of 
>>>the JellyContext
>>>and add a cache of compiled scripts inside the context (indexed by 
>>>uri/url) ?
>>>
>>>Also I am not sure how to handle the 'export' and 'inherit' parameters 
>>>when I use compileScript+run instead of a single call to runScript().
>>>
>>>You say a Tag isn't compilable, but what's the "CompilableTag" ??
>>>I tried to use it the but the attributes (uri,...) of my tag are empty 
>>>when "compile" is called.
>>>
>>>Thanks for your help!
>>>
>>>
>>>
>>>.Hans Gilde wrote:
>>>
>>>
>>>
>>>   
>>>
>>>      
>>>
>>>>You could easily cache the imported script the first time it's run. This
>>>>     
>>>>
>>>>        
>>>>
>>is
>> 
>>
>>    
>>
>>>>a simple modification to the current import tag, so that it keeps the
>>>>reference to the script. If you do this, why not add an attribute "cache"
>>>>  
>>>>
>>>>     
>>>>
>>>>        
>>>>
>>>to
>>>
>>>
>>>   
>>>
>>>      
>>>
>>>>turn caching on/off and then submit it as a patch to the import tag?
>>>>
>>>>It would be a little harder, but not at all impossible, to make it cache
>>>>  
>>>>
>>>>     
>>>>
>>>>        
>>>>
>>>the
>>>
>>>
>>>   
>>>
>>>      
>>>
>>>>imported script at compile time.
>>>>
>>>>If not, the basic idea is this:
>>>>
>>>>A Tag isn't compilable, it's generated at runtime. A Script is
>>>>        
>>>>
>compilable,
>  
>
>>>>it's generated at compile time. You need a special Script, not a special
>>>>Tag. Scripts are very much like tags except that they need to be thread
>>>>safe. Most of the time, a Script called TagScript is used. By default,
>>>>     
>>>>
>>>>        
>>>>
>>this
>> 
>>
>>    
>>
>>>>Script creates and caches Tag instances when it's run.
>>>>
>>>>Your new Script would compile the import at compile time. The result of
>>>>compiling the import is, it self, a Script instance. At runtime, your
>>>>  
>>>>
>>>>     
>>>>
>>>>        
>>>>
>>>Script
>>>
>>>
>>>   
>>>
>>>      
>>>
>>>>would simply pass control to the imported Script.
>>>>
>>>>You would also have to implement a custom TagLibrary. A TagLibrary gets
>>>>        
>>>>
>to
>  
>
>>>>create a TagScript (implements Script) for every XML tag in its
>>>>        
>>>>
>namespace.
>  
>
>>>>So, your TagLibrary would create a custom TagScript that would compile
>>>>        
>>>>
>and
>  
>
>>>>keep the imported XML.
>>>>
>>>>-----Original Message-----
>>>>From: Arnaud Masson [mailto:am@kikamedical.com] 
>>>>Sent: Saturday, December 04, 2004 6:07 PM
>>>>To: commons-user@jakarta.apache.org
>>>>Subject: [Jelly] nested compileScript() with import ?
>>>>
>>>>hi
>>>>
>>>>in the current version of jelly "import" tag, it seems that imported 
>>>>scripts are always parsed and recompiled each time the containing script 
>>>>runs,
>>>>even if this script has already been compiled.
>>>>
>>>>the problem is that  it isn't optimized if the compiled version of the 
>>>>main script is cached.
>>>>
>>>>is it possible to compile all scripts included via <j:import ...> via
a 
>>>>single call to jellyContext.compileScript() on the containing script ?
>>>>should i write a custom tag to implement that (to replace import) ?
>>>>
>>>>thanks in advance
>>>>
>>>>arnaud
>>>>
>>>>
>>>>
>>>>
>>>>---------------------------------------------------------------------
>>>>To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
>>>>For additional commands, e-mail: commons-user-help@jakarta.apache.org
>>>>
>>>>
>>>>
>>>>
>>>>  
>>>>
>>>>     
>>>>
>>>>        
>>>>
>>>---------------------------------------------------------------------
>>>To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
>>>For additional commands, e-mail: commons-user-help@jakarta.apache.org
>>>
>>>
>>>---------------------------------------------------------------------
>>>To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
>>>For additional commands, e-mail: commons-user-help@jakarta.apache.org
>>>
>>>
>>>
>>>
>>>   
>>>
>>>      
>>>
>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
>>For additional commands, e-mail: commons-user-help@jakarta.apache.org
>>
>>
>> 
>>
>>    
>>
>
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
>For additional commands, e-mail: commons-user-help@jakarta.apache.org
>
>
>  
>


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message