XML error when using RTI DDS 5.1 and ArcObjects 10.0 in Java

7 posts / 0 new
Last post
Offline
Last seen: 9 years 9 months ago
Joined: 06/06/2014
Posts: 4
XML error when using RTI DDS 5.1 and ArcObjects 10.0 in Java

Using the open source version of DDS 5.1 and Java, I'm getting a fatal XML parsing error calling get_default_participant_qos() on the DomainParticipantFactory class.  Here is the error stack:

RTIXMLParser_parseFromString:!initialize parser
DDS_XMLParser_parse_from_string:Error parsing string
DDS_QosProvider_load_builtin_profilesI:ERROR: loading profiles
DDS_QosProvider_load_profilesI:ERROR: loading profiles
DDS_DomainParticipantFactory_load_profilesI:!load profiles
DDS_DomainParticipantFactory_get_default_participant_qos:ERROR: loading profiles
2014-06-06 16:28:05,941 FATAL [main] Bootstrap - Exception caught in main
com.rti.dds.infrastructure.RETCODE_ERROR
        at com.rti.dds.util.Utilities.rethrow(Unknown Source)
        at com.rti.dds.infrastructure.RETCODE_ERROR.check_return_codeI(Unknown Source)
        at com.rti.dds.infrastructure.NativeStructMixin.get_untypedI(Unknown Source)
        at com.rti.dds.domain.DomainParticipantFactoryImpl.get_default_participant_qos(Unknown Source)


The Java application I'm working on also makes use of ESRI ArcObjects 10.0 SP5 to do geoprocessing of the data received through DDS.  I've found that if you comment out the ESRI API calls to initialize the ArcObjects license and perform other functions, the error no longer occurs and the default QoS object is successfully created with no errors.  So it appears to be caused by some kind of internal conflict between the DDS and ArcObjects libraries that affects the DDS XML parser. 

This error didn't happen with this program running under DDS 5.0 and at this point I'm only migrating the environment from 5.0 to 5.1 without making any code changes, however I did get the same parsing error on USER_QOS_PROFILES.xml under 5.0 but was able to work around that one.

This might be a rare combination of libraries in a single Java program, but I was wondering if anyone else has seen a similar error or had any thoughts about what could be causing it.

rip
rip's picture
Offline
Last seen: 8 hours 42 min ago
Joined: 04/06/2012
Posts: 324

Hi Jeff,

We use Expat (http://expat.sourceforge.net/ version 1.95.7) for the QoS file parsing.  ArcObjects may be using a different version of Expat.

In Java, this is a case to use classloader objects with different classpath settings.  You might try loading the JNI (nddsjava[d].jar) using a created-for-the-purpose classloader object.  No guarantees. 

java.lang.classloader   also, this

First remove nddsjava.jar from the -classpath to the JVM, then explicitly load the jar via <ClassLoader>.loadClass(path.to.nddsjava.jar).  I'd experiment with putting the directory path ($NDDSHOME/class) in -classpath, which might allow you to simply <ClassLoader>.loadClass("nddsjava.jar") .


Hope this helps.  Experiment a bit, and let us know what works/what you find.

Offline
Last seen: 9 years 9 months ago
Joined: 06/06/2014
Posts: 4

It took a little time to research how to do this and get all the calls to the Java reflection API's right, but I managed to test the separate classloader approach and I still see the same error message occurring as before. For reference the code fragment is pasted below and the error occurs on the very last line, which corresponds to the same call to get_default_participant_qos() that was erroring out before. It was worth a try, also I tried running the DDS subscriber in a separate thread but got the same error. At this point the only option left I can think of is to run the DDS subscriber in a separate process from the ArcObjects piece so that the conflicting native libraries won't both be loaded in the same process. I'll have to use a UDP or TCP socket or something similar to pass the data between the processes which is an unfortunate extra hop to have to add.

Thanks for the input, and any other thoughts are welcome.

// lookup $NDDSHOME
Map<String, String> env = System.getenv();
String NDDSHOME = env.get("NDDSHOME");
logger.debug("NDDSHOME is " + NDDSHOME);

// Load nddsjava.jar in separate classloader
String ddsJarURLPath = "file:///" + NDDSHOME + "/class/nddsjava.jar";

try {
URL ddsJarURL = new URL(ddsJarURLPath);
URL[] urls = { ddsJarURL };
cl = new URLClassLoader(urls);
DomainParticipantFactoryClass = cl.loadClass("com.rti.dds.domain.DomainParticipantFactory");
DomainParticipantQosClass = cl.loadClass("com.rti.dds.domain.DomainParticipantQos");

} catch (MalformedURLException e) {
logger.fatal("MalformedURLException on dynamically loading nddsjava.jar");
logger.fatal("Path was " + ddsJarURLPath);
} catch (ClassNotFoundException ex) {
logger.fatal("ClassNotFoundException on dynamically loading nddsjava.jar");
logger.fatal(ex.getMessage());
}

Object dpQos = DomainParticipantQosClass.newInstance();
Field field = DomainParticipantFactoryClass.getField("TheParticipantFactory");
Object theParticipantFactory = field.get(null);
Class[] get_default_participant_qos_parms = { DomainParticipantQosClass };
Method get_default_participant_qos = DomainParticipantFactoryClass.getDeclaredMethod("get_default_participant_qos", get_default_participant_qos_parms );
get_default_participant_qos.invoke(theParticipantFactory, dpQos);

rip
rip's picture
Offline
Last seen: 8 hours 42 min ago
Joined: 04/06/2012
Posts: 324

Hi Jeff,

Can you set out what i'd need to reproduce the error?  (including a base install/setup of ArgObjects). 

Regards,

rip

Offline
Last seen: 9 years 9 months ago
Joined: 06/06/2014
Posts: 4

Basically you'd have to install one of the ArcGIS products (desktop or server) version 10.0 and open source RTI DDS 5.1 on a box somewhere and run a simple Java program that just initializes the ArcEngine license and then tries to create the default QoS object. We run this on an ArcGIS server on Linux, if that affects it. The arcobjects.jar and nddsjava.jar both need to be on the classpath as well as having the arcobjects and DDS native library paths set on the JVM command line with -Djava.library.path="..." and/or the LD_LIBRARY_PATH environment variable. ArcObjects for some reason needs an X display running to initialize, so our startup script includes this to create a headless X display before launching the JVM:

if [ ! -e /tmp/.X500-lock ]; then
Xvfb :500 -screen 0 1280x1024x24 &
fi
export DISPLAY=localhost:500.0

Make sure you are running a 32-bit JVM because ArcObjects 10.0 won't work with 64-bit. I think that's all the environment setup, then a simple Java program with a main routine like this should throw the error:

EngineInitializer.initializeEngine();
AoInitialize aoInit = new AoInitialize();
try {
if (aoInit.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeEngine) ==
esriLicenseStatus.esriLicenseAvailable) {
aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
System.out.println("Initialized an ArcEngine license");
} else if (aoInit.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeArcServer) ==
esriLicenseStatus.esriLicenseAvailable) {
aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeArcServer);
System.out.println("Initialized an ArcGIS Server license");
} else {
System.err.println("Cannot find an available ESRI license, exiting");
System.exit(0);
}
} catch (Exception e) {
System.err.println("Exception occurred initializing ESRI license, exiting");
System.err.println(e);
System.exit(0);
}

DomainParticipantQos participant_qos = new DomainParticipantQos();
DomainParticipantFactory.TheParticipantFactory.get_default_participant_qos(participant_qos);

rip
rip's picture
Offline
Last seen: 8 hours 42 min ago
Joined: 04/06/2012
Posts: 324

Hi,

ESRI's website is not user friendly, I can't find a download of either the desktop or server product.  the 30 day eval is only valid for the cloud based access.  

And my email to their support address was ... ineffective.  They won't talk to me because I'm not a customer.  

I'm assuming you're a customer, you might email them and see if they'll talk to you.

Sorry,

rip

Offline
Last seen: 9 years 9 months ago
Joined: 06/06/2014
Posts: 4

We are ESRI EDN customers, but we're going forward with the two-process approach to workaround this since we've tested it and it works. Process A connects to the DDS topic and creates a java.net.ServerSocket to start listening on a local port, process B connects to the port using a java.net.Socket. Then process A begins writing each received DDS message over the socket as a serialized object using java.io.ObjectOutputStream and process B receives it and de-serializes it using java.io.ObjectInputStream, and does the geoprocessing with the ESRI libraries. They can both be launced simultaneously with a script, so while not ideal it's also not too bad.

Thanks again for the input on this.