You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@activemq.apache.org by "Gary Tully (JIRA)" <ji...@apache.org> on 2012/05/17 16:39:07 UTC

[jira] [Resolved] (AMQ-3844) NullPointerException when removing connection info

     [ https://issues.apache.org/jira/browse/AMQ-3844?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Gary Tully resolved AMQ-3844.
-----------------------------

       Resolution: Fixed
    Fix Version/s: 5.6.0
         Assignee: Gary Tully

fix related to https://issues.apache.org/jira/browse/AMQ-3305
                
> NullPointerException when removing connection info
> --------------------------------------------------
>
>                 Key: AMQ-3844
>                 URL: https://issues.apache.org/jira/browse/AMQ-3844
>             Project: ActiveMQ
>          Issue Type: Bug
>          Components: Broker
>    Affects Versions: 5.4.3, 5.5.1
>         Environment: Linux 2.6.18-274.12.1.el5 #1 SMP Tue Nov 29 13:37:35 EST 2011 i686 athlon i386 GNU/Linux, Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
>            Reporter: Antonio D'Errico
>            Assignee: Gary Tully
>             Fix For: 5.6.0
>
>         Attachments: ActiveMQ_server.log, jBoss_server.log
>
>
> Sometimes off and on the ActiveMQ server, the KahaDB maintains some old transactions that try to recovery. So at start up these transactions are added to the {{xaTransactions}} map inside {{TransactionBroker}} with a null {{ConnectionId}}.
> This is the stack trace of the recovery at startup:
> {code:none} 
> 	TransactionBroker.beginTransaction(ConnectionContext, TransactionId) line: 152	
> 	TransactionBroker$1.recover(XATransactionId, Message[], MessageAck[]) line: 92	
> 	KahaDBTransactionStore.recover(TransactionRecoveryListener) line: 317	
> 	TransactionBroker.start() line: 89	
> 	BrokerService$3.start() line: 1781	
> 	XBeanBrokerService(BrokerService).start() line: 489	
> 	XBeanBrokerService.afterPropertiesSet() line: 60	
> 	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
> 	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
> 	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
> 	Method.invoke(Object, Object...) line: 597	
> 	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).invokeCustomInitMethod(String, Object, RootBeanDefinition) line: 1536	
> 	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).invokeInitMethods(String, Object, RootBeanDefinition) line: 1477	
> 	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).initializeBean(String, Object, RootBeanDefinition) line: 1409	
> 	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 519	
> 	DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 456	
> 	AbstractBeanFactory$1.getObject() line: 291	
> 	DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222	
> 	DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 288	
> 	DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 190	
> 	DefaultListableBeanFactory.preInstantiateSingletons() line: 574	
> 	XBeanBrokerFactory$1(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 895	
> 	XBeanBrokerFactory$1(AbstractApplicationContext).refresh() line: 425	
> 	XBeanBrokerFactory$1(ResourceXmlApplicationContext).<init>(Resource, List) line: 64	
> 	XBeanBrokerFactory$1(ResourceXmlApplicationContext).<init>(Resource) line: 52	
> 	XBeanBrokerFactory$1.<init>(XBeanBrokerFactory, Resource) line: 115	
> 	XBeanBrokerFactory.createApplicationContext(String) line: 115	
> 	XBeanBrokerFactory.createBroker(URI) line: 71	
> 	BrokerFactory.createBroker(URI, boolean) line: 71	
> 	BrokerFactory.createBroker(URI) line: 54	
> 	StartCommand.startBroker(URI) line: 115	
> 	StartCommand.runTask(List<String>) line: 74	
> 	StartCommand(AbstractCommand).execute(List<String>) line: 57	
> 	ShellCommand.runTask(List<String>) line: 143	
> 	ShellCommand(AbstractCommand).execute(List<String>) line: 57	
> 	ShellCommand.main(String[], InputStream, PrintStream) line: 85	
> 	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
> 	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
> 	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
> 	Method.invoke(Object, Object...) line: 597	
> 	Main.runTaskClass(List<String>) line: 251	
> 	Main.main(String[]) line: 107	 
> {code} 
> During the  runtime the client tries to add and remove connections; sometimes the removeConnection throws a NPE due to these transactions without ConnectionID.
> Take a look to the code fragment from {{TransactionBroker}}:
> {code:java}
>     public void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error) throws Exception {
>         for (Iterator<Transaction> iter = context.getTransactions().values().iterator(); iter.hasNext();) {
>             try {
>                 Transaction transaction = iter.next();
>                 transaction.rollback();
>             } catch (Exception e) {
>                 LOG.warn("ERROR Rolling back disconnected client's transactions: ", e);
>             }
>             iter.remove();
>         }
>         synchronized (xaTransactions) {
>             // first find all txs that belongs to the connection
>             ArrayList<XATransaction> txs = new ArrayList<XATransaction>();
>             for (XATransaction tx : xaTransactions.values()) {
>                 if (tx.getConnectionId().equals(info.getConnectionId()) && !tx.isPrepared()) {
>                     txs.add(tx);
>                 }
>             }
>             // then remove them
>             // two steps needed to avoid ConcurrentModificationException, from removeTransaction()
>             for (XATransaction tx : txs) {
>                 try {
>                     tx.rollback();
>                 } catch (Exception e) {
>                     LOG.warn("ERROR Rolling back disconnected client's xa transactions: ", e);
>                 }
>             }
>         }
>         next.removeConnection(context, info, error);
>     }
> {code}
> as you can see inside the loop there is a check for {{tx.getConnectionId().equals(info.getConnectionId())}} that throws the NPE. When this occurs the connection isn't removed. This information isn't shared with the client that believes the opposite, so the next time that try to resend client information to server obtain (under jBoss) this error {{javax.transaction.xa.XAException: Broker: AMQ - Client: ID:srv001-47592-1336730655955-64:2 already connected from /127.0.0.1:49806}}
> that can be bound to the former server fails.
> This scenario can be found inside the attached logs.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira