Native library and ignition issue

Hello everyone,

I encountered a problem by using ignition with a native library. What that mean, I explain now in details.

Why a native library?
I have an old Delphi created wsdl file from a client which must be used in one expression function within ignition to create a SOAP connection. Unfortunately, the wsdl is not compatible with Java, so I had no other choice than using the old existing C# code and write a Wrapper in C++ to generate a native library. To write the wrapper, I used to following tutorial. However, if you want to try out the code for your own, you need to know, that __gc is deprecated and you have to use ref now instead.

What is the problem?

I call the native C++ library from Java using JNI. This works quite fine when I ran the code from a command shell, however, as a module installed in inductive automation, it does not work at all. I presented the problem first to Travis Cox, who told me that the scan class hangs up for some reason but he could not find out why. Therefore, he suggested me to write this forum post.

Files in use SomaTest.zip (32.1 KB)

The SomaTest.rar file containing the files which are necessary to run to project. Just unpack the folder and run the runnable jar inside the folder. The result is a printed stacktrace (because you can’t reach the SOAP server from your side) and the result -999999 at the end (a house ruled value to signify that anything went wrong, here the connection to the soap server).

Within inductive automation, this (so, -999999) should also be visualized but NA is shown because the scan class hangs up for any reason.

Finally, here is the inductive automation code. PaulWurthExpressionFunctions.zip (223.0 KB)

I hope anyone have an idea why the scan class doesn’t like to do the same than the command shell?

Thank you in advance

My software is not convinced that either of your RAR files are actually RAR (or zip, or anything) files. Can you re-upload as something else?

Ok I uploaded them again as original zip files. Previously I used 7zip sorry.

Have you looked at a thread dump after this scan class hangs up?

Hi Kevin,

Travis Cox told me that the scan class hangs up. I personally can not see anything on me side. I can just install a module and look at the log files created, which unfortunately say nothing.

Why don’t you get a thread dump from the gateway when it hangs and upload it here.

Also, if it turns out it’s not blocked somewhere in the module or native code, my next suggestion would be to wrap the call to System.load in a try/catch for Throwable and log the exception to see if that call is failing.

Hi Kevin,

I am sorry but maybe we talked past each other or I was not clear enough or simply not able to understand what you suggest. But let me explain it again and we will see.

  1. I have a server where the Ignition Designer 7.9.4-beta1 is installed
  2. I created a project PaulWurthExpressionFunctions (which is attached in the first post)
  3. I created a .modl file
  4. I installed the .modl file with the ignition web interface (CONFIGURE → Modules → Install or Upgrade a Module)
  5. I started the designer and the result is what you see on the picture
  6. I took a look at the logs which tells nothing more than this:

java.io.IOException: An existing connection was forcibly closed by the remote host. This is normal, because the SOAP server is not reachable and the result is therefore -999999 and not NA. This result you can see, if you run the SomaTest I also attached. wrapper.zip (231.4 KB)

I don’t know how I should do a thread dump because I can’t run the project within eclipse. So if you know how I can do it with what I listed, please tell me. By the way, I am not allowed to install any third person programs on the machine.

Thank you

On the Ignition gateway in the Status section, go to Diagnostics > Logs, then click the download button. Do this while the scan class is stuck.

Hi Kevin,

Thank you for your explanation. However, the only diagnostics I found is under Help → Diagnostics

Log Viewer: There is no download button and the messages here are somehow limited

Thread Viewer: Here you can see some more details, but no one helps in my eyes. However, there is also no download button. In the picture you an see the one I thought would be the most relevant.

So what did I wrong? If I missed something, please tell me.

Thank you,
Pfeiffer Alain

That’s the diagnostics in the client/designer. You need to use the web administration interface to get logs on the gateway.

Thank you pturmel I will check it.

Hi,

Here are the diagnostic logs system_logs_06Sep2017-10-16-14.zip (528.1 KB)

Can you get a thread dump from the Threads page that’s right next to the Logs page in the gateway? Taken while the expression has made the scan class appear to stop.

I am sorry, but by clicking on the download button, a Blank Page is shown instead of downloading the package.

To be sure, that I used the right one, here is a screen:

Yeah, that’s the page…

Can you try it in a different browser and let us know what version of IE that you’re attempting with?

Yeah the problem was IE11 but I was not allowed to install another browser on the machine. I used now firefox portable and it did the job. thread_dump.txt (69.3 KB)

I loaded your module and created an expression tag that uses your SomaValue function. It results in this error in the console:

java.lang.ExceptionInInitializerError: null
	at com.paulwurth.expressionfunctions.SomaValue.execute(SomaValue.java:48)
	at com.inductiveautomation.ignition.common.expressions.FunctionExpression.execute(FunctionExpression.java:69)
	at com.inductiveautomation.ignition.gateway.sqltags.execution.tags.ExpressionTag$ELExecutor.internalExecute(ExpressionTag.java:464)
	at com.inductiveautomation.ignition.gateway.sqltags.execution.tags.ExpressionTag$Executor.execute(ExpressionTag.java:314)
	at com.inductiveautomation.ignition.gateway.sqltags.execution.tags.ExpressionTag.internalEvaluate(ExpressionTag.java:236)
	at com.inductiveautomation.ignition.gateway.sqltags.execution.tags.AbstractExecutableTag.evaluate(AbstractExecutableTag.java:543)
	at com.inductiveautomation.ignition.gateway.sqltags.scanclasses.BasicScanClassInstance.evaluateTags(BasicScanClassInstance.java:177)
	at com.inductiveautomation.ignition.gateway.sqltags.scanclasses.BasicScanClassInstance.runTagEvaluation(BasicScanClassInstance.java:164)
	at com.inductiveautomation.ignition.gateway.sqltags.scanclasses.SimpleExecutableScanClass.runTagEvaluation(SimpleExecutableScanClass.java:813)
	at com.inductiveautomation.ignition.gateway.sqltags.scanclasses.SimpleExecutableScanClass.run(SimpleExecutableScanClass.java:925)
	at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$SelfSchedulingRunner.run(BasicExecutionEngine.java:511)
	at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$TrackedTask.run(BasicExecutionEngine.java:593)
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException: null
	at sun.awt.shell.Win32ShellFolder2.access$200(Unknown Source)
	at sun.awt.shell.Win32ShellFolder2$1.call(Unknown Source)
	at sun.awt.shell.Win32ShellFolder2$1.call(Unknown Source)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at sun.awt.shell.Win32ShellFolderManager2$ComInvoker$3.run(Unknown Source)
	... 1 common frames omitted

This is pointing to your static initializer in SomaCommunicator throwing an exception:

	static {
//		System.load(loadFile("SomaWrapper.dll"));
		System.load(FolderFinder.getFolderLocation("Soma") + "\\SomaWrapper.dll");
	}

The scan class is indeed stopping because of the uncaught java.lang.ExceptionInInitializerError

Seems like your problem to debug from here.

Hi Kevin,

I am sorry I forgot to explain you that I changed the way how the code loads the SomaWrapper.dll in the final project :frowning: If you take a look at the FolderFinder class, it looks for a folder “Soma” under:

  • Local Disk (e,g, C, D, …)

  • Local Disk/…/Inductive automation (e.g. C:/Program Files/inductive Automation)

I did that, because I didn’t know what the project folder in inductive automation is.

Just create a folder “Soma” under C for example and put all files needed into the folder and it should work:

  • CommunicateWithIndas.dll

  • Soma_Communication_Java.netmodule

  • SomaWrapper.dll

How I did it:

Sorry again that I forgot to mention that. I told it to Travis but forgot to add this detail here. Another option, would be to simply point to the folder you have:

System.load(“Path to SomaWrapper.dll”); //Pay attention, SomaWrapper need to have both other files located in the same loction.

Once I set the Ignition service to run as my user instead of the service account I got one step further. There’s some kind of permissions error with the file functions you’re using and running as a service that was leading to the NPE.

Now the error has something to do with your DLL and its dependencies:

java.lang.UnsatisfiedLinkError: C:\Program Files\Inductive Automation\Soma\SomaWrapper.dll: Can't find dependent libraries
	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
 	at java.lang.ClassLoader.loadLibrary0(Unknown Source)
 	at java.lang.ClassLoader.loadLibrary(Unknown Source)
	at java.lang.Runtime.load0(Unknown Source)
 	at java.lang.System.load(Unknown Source)
 	at lu.paulwurth.SomaCommunicator.<clinit>(SomaCommunicator.java:10)
	at com.paulwurth.expressionfunctions.SomaValue.execute(SomaValue.java:48)
	at com.inductiveautomation.ignition.common.expressions.FunctionExpression.execute(FunctionExpression.java:70)

Hi Kevin,

As already explained, SomaWrapper needs two ressources:

  1. Soma_Communication_Java.netmodule

  2. CommunicateWithIndas.dll

These two files MUST be in the same location than SomaWrapper. If you run the runnable jar in SomaTest.rar, you should see the -999999 value at the end (after the printed stack trace that the SOAP connection failed).

UnsatisfiedLinkError means that the two files are not correctly placed. On my side, when I run the test Program I wrote in Eclipse, it runs fine. So it should also run fine within inductive automation. Here is the source code of the SomaTest.rar program SomaCommunicator.zip (55.5 KB)

This one should run on your side and vizualize the following:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://pc_soma:1024/soap/Indas_SOAP_Service that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. —> System.Net.WebException: The remote name could not be resolved: ‘pc_soma’
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
at System.Net.HttpWebRequest.GetRequestStream()
at System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.GetOutputStream()
— End of inner exception stack trace —

Server stack trace:
at System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.GetOutputStream()
at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object ins, Object outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at CommunicateWithIndas.IndasSoap.INDAS_SOAP_SERVICE.SetChannels(SetChannelsRequest request)
at CommunicateWithIndas.IndasSoap.NDAS_SOAP_SERVICEClient.CommunicateWithIndas.IndasSoap.INDAS_SOAP_SERVICE.SetChannels(SetChannelsRequest request)
at CommunicateWithIndas.IndasSoap.NDAS_SOAP_SERVICEClient.SetChannels(Int32 Channels)
at CommunicateWithIndas.Soma_Communication.GetValueFromSOMA(Int32 dataWanted)
— End of inner exception stack trace —
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object parameters, Object arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture)
at CSharpSomaConnector.GetValue(Int32 value)
at Java_lu_paulwurth_SomaCommunicator_getSomaValue(JNIEnv_* jn, _jobject* jobj, Int32 value)
-999999.0

This is a printed stack trace, because the SOAP server is not reachable and the result is -999999.0. This should be the same in inductive automation. If this is not the case, as on my side, the problem is somewhere, but not in my code, because it runs just fine outside of inductive automation.

Thank you for your help