tliron / prudence

An opinionated lightweight web framework built for scale
https://prudence.threecrickets.com
Apache License 2.0
13 stars 5 forks source link

Is executeOnce for a library allowed in handler ? #27

Closed GoogleCodeExporter closed 3 years ago

GoogleCodeExporter commented 9 years ago
1) What's the problem?
 java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableMap.put(Unknown Source)
    at com.threecrickets.prudence.service.DocumentService.markExecuted(DocumentService.java:164)
    at com.threecrickets.prudence.service.DocumentService.executeOnce(DocumentService.java:138)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:161)

2) How can someone else reproduce it?
Not sure if a simple example be made...  But this is what's in play:

1. A handler, "check_session.js" is made into a filter in routes.js via:

  router.filterBase(dynamicWebBaseURL, '/check_session/', applicationInstance.context, dynamicWeb).next

2. The check_session.js handler on line #4 executes: 
document.executeOnce('../libraries/tgxpost/login_api/');
3. The login_api.js library on line#6 executes a single 
document.executeOnce('../libraries/tgxpost/db_connect_ex/');

There are no other executes or executeOnce at all in the handler or either 
library.

The db_connect_ex library does not perform any executeOnces.

I believe the error is surfacing from the "attributes.put" 
(DocumentService.java:164) but that is as far as I can take it.

Map<String, Object> attributes = executionContext.getAttributes();
                        @SuppressWarnings("unchecked")
                        Set<String> executed = (Set<String>) attributes.get( EXECUTED_ATTRIBUTE );
                        if( executed == null )
                        {
                                executed = new HashSet<String>();
                                attributes.put( EXECUTED_ATTRIBUTE, executed );
                        }

From the error message it looks like the attributes returned by 
executionContext.getAttributes is an $UnmodifiableMap  ?

Is it ok to executeOnce in a handler ?  Perhaps the handler is not created 
correctly as a filter ?

3) What flavor of the Prudence are you using? Which version, and on what
operating system?
Javascript, Windows XP.

4) Please provide any additional information below:

Here is my log

2012-03-09 16:31:49,842: WARN  [com.hazelcast.impl.Node] [dev] Neither 
multicast nor tcp/ip join is enabled! Starting standalone.
2012-03-09 16:31:51,201: INFO  [com.threecrickets.prudence.cache.H2Cache] Up! 
org.apache.commons.dbcp.PoolingDataSource@da2cef
2012-03-09 16:31:52,732: INFO  [unknown.jul.logger] Routing.js: attached libs 
to staticBaseURL: /libs/
2012-03-09 16:31:53,514: INFO  [org.restlet.Component.InternalRouter] Starting 
the HTTP client
2012-03-09 16:31:53,529: INFO  [org.restlet.Component.InternalRouter] Starting 
the HTTP client
2012-03-09 16:31:53,654: INFO  [org.eclipse.jetty.util.log] 
jetty-7.2.2.v20101205
2012-03-09 16:31:53,732: INFO  [org.eclipse.jetty.util.log] Started 
SelectChannelConnector@0.0.0.0:8080
2012-03-09 16:31:53,889: DEBUG [prudence.coolbuddy.preheat] Preheating: 
/coolbuddy/addpost.htm/
2012-03-09 16:31:53,889: DEBUG [prudence.coolbuddy.preheat] Preheating: 
/coolbuddy/index.html/
2012-03-09 16:31:53,889: DEBUG [prudence.coolbuddy.preheat] Preheating: 
/coolbuddy/addtag.htm/
2012-03-09 16:31:53,889: DEBUG [prudence.coolbuddy.preheat] Preheating: 
/coolbuddy/login.htm/
2012-03-09 16:31:53,889: DEBUG [prudence.coolbuddy.preheat] Preheating: 
/coolbuddy/home.html/
2012-03-09 16:31:54,154: ERROR [prudence.coolbuddy] Exception or error caught 
in handler
com.threecrickets.scripturian.exception.ExecutionException: Wrapped 
java.lang.UnsupportedOperationException (check_session.js#4)
    at com.threecrickets.scripturian.adapter.RhinoAdapter.createExecutionException(Unknown Source)
    at com.threecrickets.scripturian.adapter.RhinoAdapter.enter(Unknown Source)
    at com.threecrickets.scripturian.ExecutionContext.enter(Unknown Source)
    at com.threecrickets.scripturian.Executable.enter(Unknown Source)
    at com.threecrickets.prudence.DelegatedHandler.handle(DelegatedHandler.java:225)
    at com.threecrickets.prudence.DelegatedFilter.beforeHandle(DelegatedFilter.java:143)
    at org.restlet.routing.Filter.handle(Filter.java:201)
    at com.threecrickets.prudence.util.Fallback.handle(Fallback.java:225)
    at org.restlet.routing.Filter.doHandle(Filter.java:156)
    at org.restlet.routing.Filter.handle(Filter.java:203)
    at org.restlet.routing.Router.doHandle(Router.java:497)
    at org.restlet.routing.Router.handle(Router.java:737)
    at com.threecrickets.prudence.PrudenceRouter.handle(PrudenceRouter.java:496)
    at org.restlet.routing.Filter.doHandle(Filter.java:156)
    at org.restlet.routing.Filter.handle(Filter.java:203)
    at org.restlet.routing.Filter.doHandle(Filter.java:156)
    at org.restlet.routing.Filter.handle(Filter.java:203)
    at org.restlet.routing.Filter.doHandle(Filter.java:156)
    at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:151)
    at org.restlet.routing.Filter.handle(Filter.java:203)
    at org.restlet.routing.Filter.doHandle(Filter.java:156)
    at org.restlet.routing.Filter.handle(Filter.java:203)
    at org.restlet.engine.ChainHelper.handle(ChainHelper.java:111)
    at org.restlet.engine.application.ApplicationHelper.handle(ApplicationHelper.java:72)
    at org.restlet.Application.handle(Application.java:388)
    at com.threecrickets.prudence.PrudenceApplication.handle(PrudenceApplication.java:67)
    at org.restlet.routing.Filter.doHandle(Filter.java:156)
    at org.restlet.routing.Filter.handle(Filter.java:203)
    at org.restlet.routing.Router.doHandle(Router.java:497)
    at org.restlet.routing.Router.handle(Router.java:737)
    at org.restlet.engine.component.ComponentClientDispatcher.doHandle(ComponentClientDispatcher.java:83)
    at org.restlet.engine.TemplateDispatcher.handle(TemplateDispatcher.java:121)
    at org.restlet.engine.component.ChildClientDispatcher.parentHandle(ChildClientDispatcher.java:139)
    at org.restlet.engine.component.ChildClientDispatcher.doHandle(ChildClientDispatcher.java:91)
    at org.restlet.engine.TemplateDispatcher.handle(TemplateDispatcher.java:121)
    at org.restlet.engine.component.ChildClientDispatcher.parentHandle(ChildClientDispatcher.java:139)
    at org.restlet.engine.component.ChildClientDispatcher.doHandle(ChildClientDispatcher.java:91)
    at org.restlet.engine.TemplateDispatcher.handle(TemplateDispatcher.java:121)
    at org.restlet.engine.component.ChildClientDispatcher.parentHandle(ChildClientDispatcher.java:139)
    at org.restlet.engine.component.ChildClientDispatcher.doHandle(ChildClientDispatcher.java:91)
    at org.restlet.engine.TemplateDispatcher.handle(TemplateDispatcher.java:121)
    at org.restlet.resource.ClientResource.handle(ClientResource.java:935)
    at org.restlet.resource.ClientResource.handle(ClientResource.java:903)
    at org.restlet.resource.ClientResource.handle(ClientResource.java:858)
    at org.restlet.resource.ClientResource.handle(ClientResource.java:766)
    at org.restlet.resource.ClientResource.get(ClientResource.java:499)
    at com.threecrickets.prudence.util.PreheatTask.run(PreheatTask.java:139)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.mozilla.javascript.WrappedException: Wrapped 
java.lang.UnsupportedOperationException (check_session.js#4)
    at org.mozilla.javascript.Context.throwAsScriptRuntimeEx(Context.java:1773)
    at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:183)
    at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:247)
    at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:66)
    at applications.coolbuddy.handlers.check_session$js$0$1331326912149._c1(check_session.js:4)
    at applications.coolbuddy.handlers.check_session$js$0$1331326912149.call(check_session.js)
    at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:398)
    at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3065)
    at applications.coolbuddy.handlers.check_session$js$0$1331326912149.call(check_session.js)
    ... 52 more
Caused by: java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableMap.put(Unknown Source)
    at com.threecrickets.prudence.service.DocumentService.markExecuted(DocumentService.java:164)
    at com.threecrickets.prudence.service.DocumentService.executeOnce(DocumentService.java:138)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:161)
    ... 59 more
2012-03-09 16:31:54,154: ERROR [prudence.coolbuddy] Exception or error caught 
in handler

Original issue reported on code.google.com by tgloc...@gmail.com on 9 Mar 2012 at 10:50

GoogleCodeExporter commented 9 years ago
You did good detective work, and indeed found the issue.

Handlers stay in memory -- this allows for better performance -- and this 
includes their entire global space. So indeed the context is sealed off against 
changes. I think what should happen in this case is a silent failure -- it's OK 
if the document was not marked as executed, because it would not normally be 
executed again.

Until this is fixed, there might be several workarounds available -- this 
simplest may be to wrap the executeOnce with a try/catch.

Original comment by tal.liron on 19 Mar 2012 at 7:17

GoogleCodeExporter commented 9 years ago
Thanks Tal -

That handlers stay in memory is important to know.

The problem forced me to take a good look at my code and refactor it.
 Earlier I was constantly testing for the existence of a connection
pool and if not found, creating a lock and adding the pool to the
application globals.

I now create the pool during startup and then get and free connections
from the pool as needed.  This enabled me to lose an executeOnce from
within several libraries.  And I just went back to execute in my
handler.

Thanks again - recognizing you are busy with v2 so - till then!

Original comment by tgloc...@gmail.com on 19 Mar 2012 at 8:15