antlr / stringtemplate4

StringTemplate 4
http://www.stringtemplate.org
Other
955 stars 231 forks source link

No StringTemplate group exception in multi-thread env #194

Closed leonlee closed 6 years ago

leonlee commented 6 years ago

Hi, we met the following exception when we using JDBI 3.0.0 with Spring Scheduling:

java.lang.IllegalStateException: No StringTemplate group findAll for class interface com.xxx.dal.dao.OneDao
  at org.jdbi.v3.stringtemplate4.internal.UseStringTemplateSqlLocatorImpl.lambda$configureForType$0(UseStringTemplateSqlLocatorImpl.java:37)
  at org.jdbi.v3.sqlobject.statement.internal.CustomizingStatementHandler.locateSql(CustomizingStatementHandler.java:157)
  at org.jdbi.v3.sqlobject.statement.internal.CustomizingStatementHandler.invoke(CustomizingStatementHandler.java:134)
  at org.jdbi.v3.sqlobject.statement.internal.SqlQueryHandler.invoke(SqlQueryHandler.java:25)
  at org.jdbi.v3.sqlobject.SqlObjectFactory.lambda$null$12(SqlObjectFactory.java:157)
  at org.jdbi.v3.core.ConstantHandleSupplier.invokeInContext(ConstantHandleSupplier.java:52)
  at org.jdbi.v3.sqlobject.SqlObjectFactory.lambda$createInvocationHandler$13(SqlObjectFactory.java:156)
  at com.sun.proxy.$Proxy96.findBankAccountList1(Unknown Source)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
  at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
  at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:186)
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:299)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1147)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:622)
  at java.lang.Thread.run(Thread.java:834)

After some investigations, we found the following codes is not safe in multi-thread env that it should set alreadyLoaded after the templates have loaded, otherwise other thread may use an unloaded STGroup and throw the above execption:

https://github.com/antlr/stringtemplate4/blob/9cc59e1dceaf75f35b65864477806640336e22b2/src/org/stringtemplate/v4/STGroupString.java#L75

https://github.com/antlr/stringtemplate4/blob/9cc59e1dceaf75f35b65864477806640336e22b2/src/org/stringtemplate/v4/STGroupFile.java#L137

It looks you want to avoid repeated resources(may be many files) loading, so we suggest to add synchronized on method load to avoid other threads enter the loading process simultaneously. And rollback alreadyLoaded to false when encounter any exceptions for states consistence.

Thanks !