Wednesday, December 20, 2006

ActiveMQ... Exceptions Handling

It is strange to see such code in a mature project like ActiveMQ:

public void onException(JMSException e) {
if(exceptionListener!=null && managedConnection!=null) {
try {
exceptionListener.onException(e);
} catch (Throwable ignore) {
// We can never trust user code so ignore any exceptions.
}
}
}

(that was source code from ActiveMQ project)

Thursday, December 14, 2006

Repair after a clean

If you are owner of PDA, then probably you've heard about utils MemMaid or SKtools, and it means that this post is for you. If you not just heard, but you use it, then this post is 100% for you. If you not just use one of these programs, but also you have cleared notification queue entirely and now you don't know how to force PDA to work - ... so I am going to talk about this problem.

1. Why is it a problem? Notification queue mechanism tells PDA what actions are needed to be executed when some event is occured. For example, if you turns PDA on, then there will be an event AppRunAtWakeup (or something that is called like this). PDA does nothing on events if you cleared its notification queue. The main problem is that it will not even connect to PC with usual USB, IR or RS232 link. It means that PDA is unable to sync with PC, and you are unable to explore it from PC.

2. How can I cure it? Easiest way is to restore state of PDA from your backup. It is good idea to always have one fresh backup :))).

3. I have no backup... not really... I have one but it is ancient, what can I do in this case? You can do Hard Reset. But it is better to restore from backup, even if it is ancient :).

4. I don't want do hard reset or restore PDA from backup! Yeah, me too. Then we must add events to notification queue manually.

5. Which events do I have to add? You can do following to find out events list: make a backup, than do hard reset, install SKTools and write down events from notification queue, than restore from the recent backup. Or also you can find out events list for your PDA in internet. In my case, I looked at PDA of my wife :). She has a nearly same PDA as mine.

6. How can one add events back to notification queue? SKTools is the best that I've seen for this.

7. I have to add "\windows\repllog.exe AppRunAfterRndisFnDetected", but SKTools has no event "AppRunAfterRndisFnDetected"! Yes! It is the main problem for now. I spent four days to find such program such allows you to add this event. But I failed. There was no program for it. That is why I have written program to do that. Here it is: http://toril.ru/soft/akrndisadd.exe. Just run it on your PDA. If event is added successfully, it will show you message "True".

8. How can I place your program on PDA if I am unable to explore my PPC from PC until this event is not added?? You can move it with a help of Bluetooth, WIFI, MMC/SD/CF card, IR or RS232 link :).

Source of akrndisadd:
#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>
#include <notify.h>

int _tmain(int argc, _TCHAR* argv[])
{
TCHAR *r = TEXT ("False");

// This API is deprecated. I know.
if (CeRunAppAtEvent (TEXT("\\windows\\repllog.exe"), 14L)) {
r = TEXT ("True");
};

MessageBox (NULL, r, r, MB_OKCANCEL | MB_ICONEXCLAMATION);
return 0;
}

Tuesday, October 17, 2006

JCA

Assume that we write an JCA RA supporting outbound connections to an EIS. We have written everything. It has been verificated and deployed into GlassFish. Everything is ok. Now we have deployed some application to test connection to the EIS. We execute it and see how it fails with: "Exception in NamingManagerImpl copyMutableObject() ... java.io.NotSerializableException".

After digging, we find out, that the exception throws on copying of implementation of the java.resource.cci.ConnectionFactory interface. And exactly, there is a non-serializable field in the ConnectionFactoryImpl, (the field is) ManagedConnectionFactory for example. After N hours have bean spended/killed for search in the google, we find out, that the GlassFish puts an object copy in JNDI - not the object itself! And again, after we have blamed and decided that JNDI implementators know more, we mark the disagreeable field in the ConnectionFactoryImpl as transient. Suppose this object will be used just to invoke getReference method? No: after we have bothered with it a bit more, it turns out, that dependency injection mechanism gives us the copy of the object from the JNDI with transient fields set to NULL or zero.

Lets give GlassFish a last chance. We read its sources, and find out that not every object goes through JNDI serialized. For example, Connectors should be thrown in not serialized! Hm, but how does it find that object is a Connector? In this way:

private boolean isConnector(String logicalJndiName){
return (logicalJndiName.indexOf(EIS_STRING)!=-1);
}
where EIS_STRING = "/eis/".


In short, remember it to eliminate extra troubles: ConnectionFactory instances must be placed in subcontext /eis/ !!

In general, this problem appears in a form of NPE (null pointer exception) when method is invoked on a transient field. I think, it is a good idea to have the following code in connectionFactoryImpl:

/**
* Ensure that managedConnectionFactory is not null.
* @throws ResourceException if managedConnectionFactory is null.
*/
protected void ensureManagedConnectionFactory () throws ResourceException {
if (this.managedConnectionFactory == null) {
throw new ResourceException (
"No reference to managed connection factory exists."
+ " Either it is a bug of the RA or your JNDI resource"
+ " is not in the /eis/ subcontext");
}

Always invoke this method before use of this.managedConnectionFactory.