I am working on migrating an enterprise application from GlassFish 3.1 to WildFly. The application makes use of a JCA resource adapter, the sole purpose of which is to call a method in a native library. This is mainly to stay in compliance with the Java EE spec, which forbids direct calls to native methods in EJBs. I can confirm that the adapter loads and works correctly on GlassFish and the connection factory exposed by it can be injected as an interface reference into a CDI named bean using the @Resource annotation with the mappedName attribute.

Now moving on to WildFly, the resource adapter deploys correctly and the native library packaged in its RAR is loaded into process space (verified on 64-bit Windows with Sysinternals Process Monitor) from the ephemeral vfs directory created by the container during deployment. However, two things appear broken:

1. Any attempt to inject the connection factory reference into a named bean via its interface results in the following message:

java.lang.IllegalArgumentException: Can not set net.buildinglogix.bdx.npi.api.INativePlatformInterfaceConnectionFactory field net.buildinglogix.test.RABean.factory to net.buildinglogix.bdx.npi.impl.NativePlatformInterfaceConnectionFactory at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168) at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) at java.lang.reflect.Field.set(Field.java:741) at org.jboss.weld.injection.FieldResourceInjection.injectMember(FieldResourceInjection.java:62) at org.jboss.weld.injection.AbstractResourceInjection.injectResourceReference(AbstractResourceInjection.java:53) at org.jboss.weld.util.Beans.injectEEFields(Beans.java:348) at org.jboss.weld.injection.producer.ResourceInjector$1.proceed(ResourceInjector.java:69) at org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:48) at org.jboss.weld.injection.producer.ResourceInjector.inject(ResourceInjector.java:72) at org.jboss.weld.injection.producer.BasicInjectionTarget.inject(BasicInjectionTarget.java:121) at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:159) at org.jboss.weld.util.bean.IsolatedForwardingBean.create(IsolatedForwardingBean.java:45) at org.jboss.weld.context.AbstractContext.get(AbstractContext.java:96) at org.jboss.weld.context.PassivatingContextWrapper$AbstractPassivatingContextWrapper.get(PassivatingContextWrapper.java:76) at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.get(ContextualInstanceStrategy.java:101) at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.get(ContextualInstanceStrategy.java:178) at org.jboss.weld.bean.ContextualInstance.get(ContextualInstance.java:50) at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:761) at org.jboss.weld.el.AbstractWeldELResolver.lookup(AbstractWeldELResolver.java:107) at org.jboss.weld.el.AbstractWeldELResolver.getValue(AbstractWeldELResolver.java:90) at org.jboss.as.jsf.injection.weld.ForwardingELResolver.getValue(ForwardingELResolver.java:46)

.

.

Given that NativePlatformInterfaceConnectionFactory implements the INativePlatformInterfaceConnectionFactory, it appears that there is a classloader mismatch between the loaded JCA adapter class and the application calling into it.

2. If the first problem is overcome with the use of dynamic JNDI lookups and reflection, any attempt at calling the native method from the resource adapter code fails with UnsatisfiedLinkError.

I have done some digging around with a debugger and can confirm that the classloader used to load the native library during deployment is NOT the same as the classloader that is used to load the resource adapter classes. Furthermore, when the RA is initialized, the BootstrapContext instance passed to it does indeed have the correct classloader and that classloader correctly references the loaded native library. However, the classloader, which is used to create the RA classes themselves is different, and it does not contain any references to the native library. I believe this to be the source of the issues I listed above.

My question is: does this appear to be a bug, or are there settings in WildFly that define the level of classloader isolation that I need to set somewhere to work around this problem? I verified that if the native library is placed directly on java.library.path and is explicitly loaded with System.loadLibrary in RA initialization code (from my local classloader), the adapter works correctly. However, this is contrary to how the native library loading behavior is defined in JCA spec and may fail in other containers. Looking at the source code of org.jboss.as.connector.deployers.ra.processors.RaNativeProcessor, line 85, all the right steps are being taken, but probably in the wrong classloader. I have tried this both on WildFly 8.2.0.Final and 9.0.0CR2, and the problem exists in both environments.

Thank you for responding. The RAR is packaged as a standalone deployment. There is one JAR, which defines INativePlatformInterfaceConnectionFactory and INativePlatformInterfaceConnection. However, this JAR is being packaged in both the RAR and the EAR. Initially, the JAR was only packaged in the RAR and the EAR used it only as a compile-time dependency. This worked on GlassFish, because its classloader ends up "knowing" about all classes, which are packaged in the RAR and the application would gain access to interface definitions automatically. When I tried that on WildFly, I started getting NoClassDefFoundError on deployment and so I was forced to include the JAR inside the EAR as well. Again, I suspect that this is all due to classloader isolation in WildFly.

Thank you for responding. The RAR is packaged as a standalone deployment. There is one JAR, which defines INativePlatformInterfaceConnectionFactory and INativePlatformInterfaceConnection. However, this JAR is being packaged in both the RAR and the EAR. Initially, the JAR was only packaged in the RAR and the EAR used it only as a compile-time dependency.

EE.8.3.2 EJB Container Class Loading Requirements

Components in the EJB container must have access to the following classes and resources.

...

The contents of all jar files included in each resource adapter archive(rar file) deployed separately to the application server, if that resource adapter is used to satisfy any resource references in the module.

...

You could hack around something with jboss-deployment-structure.xml but I wouldn't recommend this. I would make sure you have a resource reference in your deployment to a resource defined by the connector (eg. @Resource). If it then still fails file a JIRA because that would be a spec violation.

If anyone is interested, I have worked around the interface visibility issue by including the RAR in my EAR file and using jboss-deployment-structure.xml per Philippe's suggestion. The deployment structure file ended up being a little different, but the idea is basically the same:

Getting around the native library loading problem was not as easy. My solution (which I admit is a huge hack) was to load the helper class, which declares the native method, into the classloader that holds the reference to the native library. This is the classloader referenced by the BootstrapContext instance, which is passed into the start method of the resource adapter. So, in my resource adapter I now have the following code:

Then in my managed connection class I load the helper class into the classloader of the BootstrapContext and use reflection to access the native method. In my case, the method takes no parameters and returns a byte array, so it was not too difficult to call. Your mileage may vary.

i think I am having the same issue (I am new to Wildfly). It started with the error message as in your original post

Can not Set (FactoryImplClass) to (FactoryInterface) then I changed the factoryInterface to what the FactoryInterface was extending which was javax.resource.cci.ConnectionFactory, If i changed it to that then it went away and then I started having the java.lang.NoClassDefFoundError . If i added the RAR inside the ear/lib i started having the java.lang.ClassCastException: com.myComp.MyCompConnector.InteractionSpec cannot be cast to com.myComp.MyCompConnector.InteractionSpec. (As there are two RARs) this also occured when i added only the jar in ear/lib. as there are two jars one in rar and one in ear/lib

Thanks for the reply. I really appreciate it Actually it seems that it is like the same problem. The only difference is that that the library is not loaded in the same class loader as the RAR itself. I actually circumvented the issue not by using the Dynamic JNDI reference lookup but by actually making the definition not to the interface itself but to the interface the interface extended.

My issue si different in the sense that i have an ear file and the EJB module is where the library within in the Rar is referenced (The library is not in the Ear or War or Jar in that package, i am expecting the External RAR to be supplying it) and that is when it says ClassDefnotFoundError. If i Add the jar in the Ear file then it loads the Class but then it says that com.comp.MyCompConnector.MyCompConnectorInspector.java cannot be cast to com.comp.MyCompConnector.MyCompConnectorInspector.java. Which looks like a classloader issue.

May be it is not the same issue but it does look like a bug in the Wildfly.

I have a war where i reference the same RAR and it gets picked up without an issue. It seems like it is only an EAR issue esp if the library/class within the RAR is referenced inside the EJB jar in the ear.

Actually What I think the problem is that : <module name="deployment.mycommunicatorappConnector-1.2.0.rar"/> never works for me, it always says Caused by: org.jboss.modules.ModuleNotFoundException: deployment.mycommunicatorappConnector-1.2.0.rar:main

even if i put it in jboss-deployment-structure.xml of a jar. (If i add it in the resource adapter definition in standalone.xml it only works with mycommunicatorappConnector-1.2.0.rar and not deployment.mycommunicatorappConnector-1.2.0.rar, so i tried both )

I moved on to another project that is on jboss and needed to run on Wildfly, it also used the same mycommunicatorappConnector rar module but had the same issue again but this time it was a simple JAR login module taht referenced a class from the rar's main jar mycommunicatorappConnector-1.2.0.jar. loginmodule cannot see deployed resource adapter

I have been dealing with this issue and still no solution.

A rar should technically be a globalmodule. It is referenced by every other application as a resource. So i tried to make it as a Global module like this:

You are trying to use a deployment as a module. If you want to use it as module (global module in your case) you should define it in module directory, because stacktrace is saying it's not finding module in that directory. For documentation on how define a module have a looke there: