Bob,
Thank you for the help. I put this in my BasePage class for convenience and it
works - still have to test in production. My problem was not paying attention
to the getThreadLocalContext() method.
public boolean resourceExists(String resourceName)
{
Context context = Context.getThreadLocalContext();
try
{
return context.getServletContext().getResource(resourceName) != null;
}
catch (MalformedURLException e)
{
e.printStackTrace();
return false;
}
}
On Dec 26, 2010, at 7:00 PM, Bob Schellink wrote:
> Ah, Velocity is trying to log to the file system which isn't allowed in GAE.
> You can off course read
> files. So perhaps instead of Velocity.resourceExists, use the servletContext
> Servlet API:
>
> public static boolean resourceExists(String resourceName) {
> ServletContext sc = Context.getThreadLocalContext();
> URL resource = servletContext.getResource(resourceName);
> return resource != null;
> }
>
> Kind regards
>
> Bob
>
> On 27/12/2010 12:40, Tim Christensen wrote:
>> Bob,
>>
>> Thank you for taking the time to help out - unfortunately the security
>> restriction kicks in:
>>
>> java.security.AccessControlException: access denied (java.io.FilePermission
>> velocity.log write)
>> at
>> java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
>> at
>> java.security.AccessController.checkPermission(AccessController.java:546)
>> at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
>> at
>> com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:166)
>> at java.lang.SecurityManager.checkWrite(SecurityManager.java:962)
>> at java.io.FileOutputStream.<init>(FileOutputStream.java:169)
>> at java.io.FileOutputStream.<init>(FileOutputStream.java:102)
>> at org.apache.log4j.FileAppender.setFile(FileAppender.java:290)
>> at
>> org.apache.log4j.RollingFileAppender.setFile(RollingFileAppender.java:194)
>> at org.apache.log4j.FileAppender.<init>(FileAppender.java:109)
>> at
>> org.apache.log4j.RollingFileAppender.<init>(RollingFileAppender.java:72)
>> at
>> org.apache.velocity.runtime.log.Log4JLogChute.initAppender(Log4JLogChute.java:118)
>> at
>> org.apache.velocity.runtime.log.Log4JLogChute.init(Log4JLogChute.java:85)
>> at
>> org.apache.velocity.runtime.log.LogManager.createLogChute(LogManager.java:157)
>> at
>> org.apache.velocity.runtime.log.LogManager.updateLog(LogManager.java:255)
>> at
>> org.apache.velocity.runtime.RuntimeInstance.initializeLog(RuntimeInstance.java:795)
>> at
>> org.apache.velocity.runtime.RuntimeInstance.init(RuntimeInstance.java:250)
>> at
>> org.apache.velocity.runtime.RuntimeInstance.requireInitialization(RuntimeInstance.java:290)
>> at
>> org.apache.velocity.runtime.RuntimeInstance.getLoaderNameForResource(RuntimeInstance.java:1462)
>> at
>> org.apache.velocity.runtime.RuntimeSingleton.getLoaderNameForResource(RuntimeSingleton.java:380)
>> at org.apache.velocity.app.Velocity.resourceExists(Velocity.java:423)
>>
>>
>>
>> On Dec 26, 2010, at 5:39 PM, Bob Schellink wrote:
>>
>>> Hi Tim,
>>>
>>> Velocity has a way to check if a template/resource exists through this
>>> static method[1]:
>>>
>>> Velocity.resourceExists(name);
>>>
>>> I'm not sure how efficient this check is though as it might touch the file
>>> system. You could ask on
>>> the Velocity mailing list just to make sure. If it does touch the file
>>> system it should be easy to
>>> cache it in your app through some utility class:
>>>
>>> VelocityUtils {
>>> private static Map<String, Integer> CACHE = new ConcurrentHashMap();
>>>
>>> public boolean resourceExists(String name) {
>>> int val = CACHE.get(name);
>>> if (val == 1) {
>>> return true;
>>> } else if (val == 0) {
>>> return false;
>>> } else {
>>> if(Velocity.resourceExists(name)) {
>>> CACHE.put(name, 1);
>>> } else {
>>> CACHE.put(name, 0);
>>> }
>>> }
>>> }
>>>
>>> or something along those lines.
>>>
>>> Id you are using GAE you should probably use 2.3.0-M1 which provides a
>>> workaround[2] for a GAE bug
>>> which breaks Page automapping.
>>>
>>> Hope this helps
>>>
>>> Kind regards
>>>
>>> Bob
>>>
>>> [1]:
>>> http://velocity.apache.org/engine/releases/velocity-1.7/apidocs/org/apache/velocity/app/Velocity.html#resourceExists(java.lang.String)
>>> [2]:
>>> http://click.apache.org/docs/extras-api/org/apache/click/extras/gae/GoogleAppEngineListener.html
>>> (See the Limitations section in the Javadoc)
>>>
>>>
>>> On 27/12/2010 10:34, Tim Christensen wrote:
>>>> I am building a web application using Click on the Google App Engine. One
>>>> of the 'features' I would
>>>> like to have is the ability to try setting a template -- if it is
>>>> available. Like the Click example
>>>> we have a BasePage > BorderPage (with a template of border.htm) and our
>>>> Page classes extend
>>>> BorderPage.
>>>>
>>>> One of those Page classes is BrandPage -- for some consumer brands. The
>>>> BrandPage will have some
>>>> common methods - search for products matching this brand for example -
>>>> think ecommerce.
>>>> Additionally, there is a brand.htm file for the BrandPage.
>>>>
>>>> However, I would like some brands, not all, to have a template available
>>>> to parse - we would like to
>>>> build out some custom .htm pages to parse in the brand.htm. For example we
>>>> may have three brands ,
>>>> A, B, C and A.htm, C.htm but not a B.htm in a directory say ...
>>>> /brand/A.htm
>>>>
>>>> Normally in the BrandPage I would put something like this:
>>>>
>>>> public String getTemplate()
>>>> {
>>>> return A.htm (or C.htm, or even B.htm)
>>>> }
>>>>
>>>> From the example above, while A.htm or C.htm exist, B.htm does not.
>>>>
>>>> How this would have happened is that when the BrandPage was requested,
>>>> with a brand id for example,
>>>> the database search would return the brand (and product etc...). I would
>>>> then 'dynamically' set the
>>>> getTemplate() return to [Normalized Brand Name].htm
>>>>
>>>> My question is this -- how can I test to see if B.htm exists before I even
>>>> set the getTemplate
>>>> return value? My focus has been using something utility-wise in Click - am
>>>> I missing a simple way to
>>>> do this? Wrap a try catch somewhere? As you would expect, I currently get
>>>> the
>>>> org.apache.velocity.exception.ResourceNotFoundException -- but I cannot
>>>> catch it in the Page in
>>>> order to do something else.
>>>>
>>>> I also want it to be a quick process. I have pondered using File to look
>>>> in a specific directory
>>>> ("/brand/file.htm"). My biggest concerns are: 1. Speed for this
>>>> 'function', 2. Google App Engine
>>>> restrictions - would looking at a file in the /war cause an issue, and
>>>> finally if Click has
>>>> something I missed as a convenience for this idea. Solving this gives us
>>>> tremendous flexibility on
>>>> the presentation and is a critical feature to our application. I am also
>>>> concerned that the way I am
>>>> thinking about this is flawed so any alternative design pattern
>>>> suggestions are welcome.
>>>>
>>>> Thank you for a great framework - I have tried nearly all of them and
>>>> Click nailed it.
>>>>
>>>
>>