今天在同一个环境启动两个项目时报错,因为两个项目同时涉及到分布式事物和切换数据源相关。
一、启动项目时报错示例:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-11-30 17:35:10.585 ERROR 7706 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'atomikosTransactionManager' defined in class path resource [com/haungtu/common/datasources/DynamicDataSourceConfig.class]:
Invocation of init method failed; nested exception is com.atomikos.icatch.SysException: Error in init: Log already in use? tmlog in ./
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1708)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:581)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:503)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243)
at com.huangtu.AdminApplication.main(AdminApplication.java:16)
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.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: com.atomikos.icatch.SysException: Error in init: Log already in use? tmlog in ./
at com.atomikos.icatch.provider.imp.AssemblerImp.createRepository(AssemblerImp.java:181)
at com.atomikos.icatch.provider.imp.AssemblerImp.assembleTransactionService(AssemblerImp.java:156)
at com.atomikos.icatch.config.Configuration.assembleSystemComponents(Configuration.java:485)
at com.atomikos.icatch.config.Configuration.init(Configuration.java:448)
at com.atomikos.icatch.jta.UserTransactionManager.startupTransactionService(UserTransactionManager.java:71)
at com.atomikos.icatch.jta.UserTransactionManager.initializeTransactionManagerSingleton(UserTransactionManager.java:60)
at com.atomikos.icatch.jta.UserTransactionManager.checkSetup(UserTransactionManager.java:52)
at com.atomikos.icatch.jta.UserTransactionManager.init(UserTransactionManager.java:122)
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.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1833)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1776)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1704)
... 24 common frames omitted
Caused by: com.atomikos.recovery.LogException: Log already in use? tmlog in ./
at com.atomikos.persistence.imp.LogFileLock.acquireLock(LogFileLock.java:59)
at com.atomikos.recovery.imp.FileSystemRepository.init(FileSystemRepository.java:55)
at com.atomikos.icatch.provider.imp.AssemblerImp.createCoordinatorLogEntryRepository(AssemblerImp.java:229)
at com.atomikos.icatch.provider.imp.AssemblerImp.createRepository(AssemblerImp.java:179)
... 38 common frames omitted
二、原因:
使用分布式事物管理时启动报错,由于在项目中使用atomikos时,如果在同一个环境中部署两个以上这种项目,则可能会报出com.atomikos.icatch.SysException: Error in init(): Log already in use异常,这个信息是因为atomikos在默认情况下是将console_file_name和log_base_name设置为默认值:tm.out和tmlog0.log,并且会将这两个文件上锁,导致其他线程无法访问,所以当多个项目都未指定这一名称时就会出现上述异常信息。
比如说:我有一个项目serviceA,一个项目serviceB,一些公共Bean,Common,Utils等都被两个项目引用,然后在本地或者同一环境中先启动一个,第二个启动必然报以上的错。
三、解决办法:
在每一个项目中都指定atomikos的文件名称,修改jta.properties文件中的
- com.atomikos.icatch.console_file_name
- com.atomikos.icatch.log_base_name
两个属性的值,保证每个项目的名称都不一样
- 注释了spring分布式事物管理相关代码,多个数据源不需要注释
欢迎关注公众号:慌途L
后面会慢慢将文章迁移至公众号,也是方便在没有电脑的情况下可以进行翻阅,更新的话会两边同时更新,大家不用担心!